Skip to content

Commit

Permalink
Use Olm CR sample from CSV
Browse files Browse the repository at this point in the history
Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com>
  • Loading branch information
AndrienkoAleksandr committed Oct 15, 2020
1 parent d93d29f commit 0d4880d
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 66 deletions.
74 changes: 39 additions & 35 deletions src/api/kube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { CHE_CLUSTER_CRD, DEFAULT_CHE_IMAGE, OLM_STABLE_CHANNEL_NAME } from '../
import { getClusterClientCommand, isKubernetesPlatformFamily } from '../util'

import { V1alpha2Certificate } from './typings/cert-manager'
import { CatalogSource, ClusterServiceVersionList, InstallPlan, OperatorGroup, PackageManifest, Subscription } from './typings/olm'
import { CatalogSource, ClusterServiceVersion, ClusterServiceVersionList, InstallPlan, OperatorGroup, PackageManifest, Subscription } from './typings/olm'
import { IdentityProvider, OAuth } from './typings/openshift'

const AWAIT_TIMEOUT_S = 30
Expand Down Expand Up @@ -1265,73 +1265,71 @@ export class KubeHelper {
}
}

async createCheClusterFromFile(filePath: string, flags: any, ctx: any, useDefaultCR: boolean): Promise<any> {
let yamlCr = this.safeLoadFromYamlFile(filePath)

async createCheCluster(CR: any, flags: any, ctx: any, useDefaultCR: boolean): Promise<any> {
const cheNamespace = flags.chenamespace
if (useDefaultCR) {
// If we don't use an explicitly provided CheCluster CR,
// then let's modify the default example CR with values
// derived from the other parameters
const cheImage = flags.cheimage
const imageAndTag = cheImage.split(':', 2)
yamlCr.spec.server.cheImage = imageAndTag[0]
yamlCr.spec.server.cheImageTag = imageAndTag.length === 2 ? imageAndTag[1] : 'latest'
CR.spec.server.cheImage = imageAndTag[0]
CR.spec.server.cheImageTag = imageAndTag.length === 2 ? imageAndTag[1] : 'latest'
if ((flags.installer === 'olm' && !flags['catalog-source-yaml']) || (flags['catalog-source-yaml'] && flags['olm-channel'] === OLM_STABLE_CHANNEL_NAME)) {
// use default image tag for `olm` to install stable Che, because we don't have nightly channel for OLM catalog.
yamlCr.spec.server.cheImageTag = ''
CR.spec.server.cheImageTag = ''
}
yamlCr.spec.server.cheDebug = flags.debug ? flags.debug.toString() : 'false'
CR.spec.server.cheDebug = flags.debug ? flags.debug.toString() : 'false'

if (isKubernetesPlatformFamily(flags.platform) || !yamlCr.spec.auth.openShiftoAuth) {
yamlCr.spec.auth.updateAdminPassword = true
if (isKubernetesPlatformFamily(flags.platform) || !CR.spec.auth.openShiftoAuth) {
CR.spec.auth.updateAdminPassword = true
}

if (!yamlCr.spec.k8s) {
yamlCr.spec.k8s = {}
if (!CR.spec.k8s) {
CR.spec.k8s = {}
}
if (flags.tls) {
yamlCr.spec.server.tlsSupport = flags.tls
if (!yamlCr.spec.k8s.tlsSecretName) {
yamlCr.spec.k8s.tlsSecretName = 'che-tls'
CR.spec.server.tlsSupport = flags.tls
if (!CR.spec.k8s.tlsSecretName) {
CR.spec.k8s.tlsSecretName = 'che-tls'
}
}
if (flags.domain) {
yamlCr.spec.k8s.ingressDomain = flags.domain
CR.spec.k8s.ingressDomain = flags.domain
}
const pluginRegistryUrl = flags['plugin-registry-url']
if (pluginRegistryUrl) {
yamlCr.spec.server.pluginRegistryUrl = pluginRegistryUrl
yamlCr.spec.server.externalPluginRegistry = true
CR.spec.server.pluginRegistryUrl = pluginRegistryUrl
CR.spec.server.externalPluginRegistry = true
}
const devfileRegistryUrl = flags['devfile-registry-url']
if (devfileRegistryUrl) {
yamlCr.spec.server.devfileRegistryUrl = devfileRegistryUrl
yamlCr.spec.server.externalDevfileRegistry = true
CR.spec.server.devfileRegistryUrl = devfileRegistryUrl
CR.spec.server.externalDevfileRegistry = true
}

yamlCr.spec.storage.postgresPVCStorageClassName = flags['postgres-pvc-storage-class-name']
yamlCr.spec.storage.workspacePVCStorageClassName = flags['workspace-pvc-storage-class-name']
CR.spec.storage.postgresPVCStorageClassName = flags['postgres-pvc-storage-class-name']
CR.spec.storage.workspacePVCStorageClassName = flags['workspace-pvc-storage-class-name']

if (flags.cheimage === DEFAULT_CHE_IMAGE &&
yamlCr.spec.server.cheImageTag !== 'nightly' &&
yamlCr.spec.server.cheImageTag !== 'latest') {
CR.spec.server.cheImageTag !== 'nightly' &&
CR.spec.server.cheImageTag !== 'latest') {
// We obviously are using a release version of chectl with the default `cheimage`
// => We should use the operator defaults for docker images
yamlCr.spec.server.cheImage = ''
yamlCr.spec.server.cheImageTag = ''
yamlCr.spec.server.pluginRegistryImage = ''
yamlCr.spec.server.devfileRegistryImage = ''
yamlCr.spec.auth.identityProviderImage = ''
CR.spec.server.cheImage = ''
CR.spec.server.cheImageTag = ''
CR.spec.server.pluginRegistryImage = ''
CR.spec.server.devfileRegistryImage = ''
CR.spec.auth.identityProviderImage = ''
}
}
yamlCr = this.overrideDefaultValues(yamlCr, flags['che-operator-cr-patch-yaml'])
CR = this.overrideDefaultValues(CR, flags['che-operator-cr-patch-yaml'])
// Back off some configuration properties(chectl estimated them like not working or not desired)
merge(yamlCr, ctx.CROverrides)
merge(CR, ctx.CROverrides)

const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi)
try {
const { body } = await customObjectsApi.createNamespacedCustomObject('org.eclipse.che', 'v1', cheNamespace, 'checlusters', yamlCr)
const { body } = await customObjectsApi.createNamespacedCustomObject('org.eclipse.che', 'v1', cheNamespace, 'checlusters', CR)
return body
} catch (e) {
throw this.wrapK8sClientError(e)
Expand Down Expand Up @@ -1545,7 +1543,7 @@ export class KubeHelper {
async createCatalogSource(catalogSource: CatalogSource) {
const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi)
try {
const namespace = catalogSource.metadata.namespace
const namespace = catalogSource.metadata.namespace!
const { body } = await customObjectsApi.createNamespacedCustomObject('operators.coreos.com', 'v1alpha1', namespace, 'catalogsources', catalogSource)
return body
} catch (e) {
Expand Down Expand Up @@ -1627,7 +1625,7 @@ export class KubeHelper {
async createOperatorSubscription(subscription: Subscription) {
const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi)
try {
const { body } = await customObjectsApi.createNamespacedCustomObject('operators.coreos.com', 'v1alpha1', subscription.metadata.namespace, 'subscriptions', subscription)
const { body } = await customObjectsApi.createNamespacedCustomObject('operators.coreos.com', 'v1alpha1', subscription.metadata.namespace!, 'subscriptions', subscription)
return body
} catch (e) {
throw this.wrapK8sClientError(e)
Expand Down Expand Up @@ -1715,7 +1713,7 @@ export class KubeHelper {
if (installPlan.status && installPlan.status.conditions) {
for (const condition of installPlan.status.conditions) {
if (condition.type === 'Installed' && condition.status === 'True') {
resolve()
resolve(installPlan)
}
}
}
Expand All @@ -1733,6 +1731,12 @@ export class KubeHelper {
})
}

async getCSV(csvName: string, namespace: string): Promise<ClusterServiceVersion | undefined> {
const csvs = await this.getClusterServiceVersions(namespace)
const csv = csvs.items.find(item => item.metadata.name === csvName)
return csv
}

async getClusterServiceVersions(namespace: string): Promise<ClusterServiceVersionList> {
const customObjectsApi = KubeHelper.KUBE_CONFIG.makeApiClient(CustomObjectsApi)
try {
Expand Down
5 changes: 4 additions & 1 deletion src/api/typings/olm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import { V1ObjectMeta } from '@kubernetes/client-node';

export interface OperatorGroup {
apiVersion: string;
kind: string;
Expand Down Expand Up @@ -41,6 +43,7 @@ export interface SubscriptionSpec {
export interface SubscriptionStatus {
conditions: SubscriptionStatusCondition[]
currentCSV: string
installedCSV?: string
installplan: InstallPlan
state: string
}
Expand Down Expand Up @@ -98,7 +101,7 @@ export interface CatalogSourceSpec {
mediatype?: string
sourceType: string
image: string
updateStrategy: CatalogSourceUpdateStrategy
updateStrategy?: CatalogSourceUpdateStrategy
}

export interface CatalogSourceUpdateStrategy {
Expand Down
47 changes: 21 additions & 26 deletions src/tasks/installers/common-tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,34 +62,29 @@ async function copyCheOperatorResources(templatesDir: string, cacheDir: string):
export function createEclipseCheCluster(flags: any, kube: KubeHelper): Listr.ListrTask {
return {
title: `Create the Custom Resource of type ${CHE_CLUSTER_CRD} in the namespace ${flags.chenamespace}`,
enabled: ctx => !!ctx.CR,
task: async (ctx: any, task: any) => {
const cheCluster = await kube.getCheCluster(flags.chenamespace)
if (cheCluster) {
task.title = `${task.title}...It already exists.`
} else {
// Eclipse Che operator supports only Multi-User Che
ctx.isCheDeployed = true
ctx.isPostgresDeployed = true
ctx.isKeycloakDeployed = true

// plugin and devfile registry will be deployed only when external ones are not configured
ctx.isPluginRegistryDeployed = !(flags['plugin-registry-url'] as boolean)
ctx.isDevfileRegistryDeployed = !(flags['devfile-registry-url'] as boolean)

const yamlFilePath = flags['che-operator-cr-yaml'] === '' ? ctx.resourcesPath + 'crds/org_v1_che_cr.yaml' : flags['che-operator-cr-yaml']
const cr = await kube.createCheClusterFromFile(yamlFilePath, flags, ctx, flags['che-operator-cr-yaml'] === '')
ctx.cr = cr
ctx.isKeycloakReady = ctx.isKeycloakReady || cr.spec.auth.externalIdentityProvider
ctx.isPostgresReady = ctx.isPostgresReady || cr.spec.database.externalDb
ctx.isDevfileRegistryReady = ctx.isDevfileRegistryReady || cr.spec.server.externalDevfileRegistry
ctx.isPluginRegistryReady = ctx.isPluginRegistryReady || cr.spec.server.externalPluginRegistry

if (cr.spec.server.customCheProperties && cr.spec.server.customCheProperties.CHE_MULTIUSER === 'false') {
flags.multiuser = false
}

task.title = `${task.title}...done.`
// Eclipse Che operator supports only Multi-User Che
ctx.isCheDeployed = true
ctx.isPostgresDeployed = true
ctx.isKeycloakDeployed = true

// plugin and devfile registry will be deployed only when external ones are not configured
ctx.isPluginRegistryDeployed = !(flags['plugin-registry-url'] as boolean)
ctx.isDevfileRegistryDeployed = !(flags['devfile-registry-url'] as boolean)

const cr = await kube.createCheCluster(ctx.CR, flags, ctx, flags['che-operator-cr-yaml'] === '')
ctx.cr = cr
ctx.isKeycloakReady = ctx.isKeycloakReady || cr.spec.auth.externalIdentityProvider
ctx.isPostgresReady = ctx.isPostgresReady || cr.spec.database.externalDb
ctx.isDevfileRegistryReady = ctx.isDevfileRegistryReady || cr.spec.server.externalDevfileRegistry
ctx.isPluginRegistryReady = ctx.isPluginRegistryReady || cr.spec.server.externalPluginRegistry

if (cr.spec.server.customCheProperties && cr.spec.server.customCheProperties.CHE_MULTIUSER === 'false') {
flags.multiuser = false
}

task.title = `${task.title}...done.`
}
}
}
Expand Down
30 changes: 26 additions & 4 deletions src/tasks/installers/olm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@

import Command from '@oclif/command'
import { cli } from 'cli-ux'
import * as yaml from 'js-yaml'
import Listr = require('listr')

import { KubeHelper } from '../../api/kube'
import { CatalogSource, Subscription } from '../../api/typings/olm'
import { CUSTOM_CATALOG_SOURCE_NAME, CVS_PREFIX, DEFAULT_CHE_OLM_PACKAGE_NAME, DEFAULT_OLM_KUBERNETES_NAMESPACE, DEFAULT_OPENSHIFT_MARKET_PLACE_NAMESPACE, KUBERNETES_OLM_CATALOG, NIGHTLY_CATALOG_SOURCE_NAME, OLM_NIGHTLY_CHANNEL_NAME, OLM_STABLE_CHANNEL_NAME, OPENSHIFT_OLM_CATALOG, OPERATOR_GROUP_NAME, SUBSCRIPTION_NAME } from '../../constants'
import { isKubernetesPlatformFamily, isStableVersion } from '../../util'

import { copyOperatorResources, createEclipseCheCluster, createNamespaceTask } from './common-tasks'
import { createEclipseCheCluster, createNamespaceTask } from './common-tasks'

export class OLMTasks {
/**
Expand All @@ -27,7 +28,6 @@ export class OLMTasks {
const kube = new KubeHelper(flags)
return new Listr([
this.isOlmPreInstalledTask(command, kube),
copyOperatorResources(flags, command.config.cacheDir),
createNamespaceTask(flags.chenamespace, flags.platform),
{
title: 'Create operator group',
Expand Down Expand Up @@ -136,6 +136,28 @@ export class OLMTasks {
task.title = `${task.title}...done.`
}
},
{
title: 'Prepare Eclipse Che cluster CR',
task: async (ctx: any, task: any) => {
const cheCluster = await kube.getCheCluster(flags.chenamespace)
if (cheCluster) {
ctx.cheClusterCreated = true
task.title = `${task.title}...It already exists..`
} else {
const subscription: Subscription = await kube.getOperatorSubscription(SUBSCRIPTION_NAME, flags.chenamespace)
const currentCSV = subscription.status!.currentCSV
const csv = await kube.getCSV(currentCSV, flags.chenamespace)
if (csv && csv.metadata.annotations) {
const CRRaw = csv.metadata.annotations!['alm-examples']
ctx.CR = (yaml.safeLoad(CRRaw) as Array<any>)[0]
} else {
throw new Error(`Unable to retrieve Che cluster CR definition from CSV: ${currentCSV}`)
}
ctx.cheClusterCreated = false
task.title = `${task.title}...Done.`
}
}
},
createEclipseCheCluster(flags, kube)
], { renderer: flags['listr-renderer'] as any })
}
Expand Down Expand Up @@ -235,8 +257,8 @@ export class OLMTasks {
enabled: ctx => ctx.isPreInstalledOLM,
task: async (_ctx: any, task: any) => {
const csvs = await kube.getClusterServiceVersions(flags.chenamespace)
const csvsToDelete = csvs.items.filter(csv => csv.metadata.name.startsWith(CVS_PREFIX))
csvsToDelete.forEach(csv => kube.deleteClusterServiceVersion(flags.chenamespace, csv.metadata.name))
const csvsToDelete = csvs.items.filter(csv => csv.metadata.name!.startsWith(CVS_PREFIX))
csvsToDelete.forEach(csv => kube.deleteClusterServiceVersion(flags.chenamespace, csv.metadata.name!))
task.title = `${task.title}...OK`
}
},
Expand Down
15 changes: 15 additions & 0 deletions src/tasks/installers/operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,21 @@ export class OperatorTasks {
}
}
},
{
title: 'Prepare Eclipse Che cluster CR',
task: async (ctx: any, task: any) => {
const cheCluster = await kube.getCheCluster(flags.chenamespace)
if (cheCluster) {
ctx.cheClusterCreated = true
task.title = `${task.title}...It already exists..`
} else {
const yamlFilePath = flags['che-operator-cr-yaml'] === '' ? ctx.resourcesPath + 'crds/org_v1_che_cr.yaml' : flags['che-operator-cr-yaml']
ctx.CR = yaml.safeLoad(fs.readFileSync(yamlFilePath).toString())

task.title = `${task.title}...Done.`
}
}
},
createEclipseCheCluster(flags, kube)
], { renderer: flags['listr-renderer'] as any })
}
Expand Down

0 comments on commit 0d4880d

Please sign in to comment.