Skip to content

Commit

Permalink
feat: allow plugins to specify dashboard pages
Browse files Browse the repository at this point in the history
  • Loading branch information
edvald authored and eysi09 committed Nov 29, 2018
1 parent 73ab7f3 commit c67b7be
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 26 deletions.
32 changes: 32 additions & 0 deletions garden-service/src/config/dashboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Joi = require("joi")
import { joiArray } from "./common"

export interface DashboardPage {
title: string
description: string
url: string
newWindow: boolean
// TODO: allow nested sections
// children: DashboardPage[]
}

export const dashboardPageSchema = Joi.object()
.keys({
title: Joi.string()
.length(32)
.required()
.description("The link title to show in the menu bar (max length 32)."),
description: Joi.string()
.required()
.description("A description to show when hovering over the link."),
url: Joi.string()
.uri()
.required()
.description("The URL to open in the dashboard pane when clicking the link."),
newWindow: Joi.boolean()
.default(false)
.description("Set to true if the link should open in a new browser tab/window."),
})

export const dashboardPagesSchema = joiArray(dashboardPageSchema)
.description("One or more pages to add to the Garden dashboard.")
13 changes: 10 additions & 3 deletions garden-service/src/config/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Primitive,
joiRepositoryUrl,
} from "./common"
import { DashboardPage } from "../config/dashboard"

export interface ProviderConfig {
name: string
Expand All @@ -32,6 +33,7 @@ export const providerConfigBaseSchema = Joi.object()

export interface Provider<T extends ProviderConfig = any> {
name: string
dashboardPages: DashboardPage[]
config: T
}

Expand All @@ -52,10 +54,14 @@ export const environmentConfigSchema = Joi.object()
.description("A key/value map of variables that modules can reference when using this environment."),
})

export interface Environment extends CommonEnvironmentConfig {
export interface EnvironmentConfig extends CommonEnvironmentConfig {
name: string
}

export interface Environment extends EnvironmentConfig {
providers: Provider[]
}

export const environmentSchema = environmentConfigSchema
.keys({
name: Joi.string()
Expand Down Expand Up @@ -85,15 +91,15 @@ export interface ProjectConfig {
name: string
defaultEnvironment: string
environmentDefaults: CommonEnvironmentConfig
environments: Environment[]
environments: EnvironmentConfig[]
sources?: SourceConfig[]
}

export const defaultProviders = [
{ name: "container" },
]

export const defaultEnvironments: Environment[] = [
export const defaultEnvironments: EnvironmentConfig[] = [
{
name: "local",
providers: [
Expand Down Expand Up @@ -142,5 +148,6 @@ export const projectSchema = Joi.object()
// this is used for default handlers in the action handler
export const defaultProvider: Provider = {
name: "_default",
dashboardPages: [],
config: {},
}
36 changes: 23 additions & 13 deletions garden-service/src/garden.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
pluginModuleSchema,
pluginSchema,
} from "./types/plugin/plugin"
import { Environment, SourceConfig, defaultProvider } from "./config/project"
import { Environment, SourceConfig, defaultProvider, Provider } from "./config/project"
import {
findByName,
getIgnorer,
Expand Down Expand Up @@ -82,7 +82,7 @@ import {
GardenPlugin,
ModuleActions,
} from "./types/plugin/plugin"
import { joiIdentifier, validate } from "./config/common"
import { joiIdentifier, validate, PrimitiveMap } from "./config/common"
import { Service } from "./types/service"
import { Task } from "./types/task"
import { resolveTemplateStrings } from "./template-string"
Expand Down Expand Up @@ -154,6 +154,7 @@ export class Garden {
private readonly hotReloadScheduler: HotReloadScheduler
private readonly taskGraph: TaskGraph

public readonly environment: Environment
public readonly localConfigStore: LocalConfigStore
public readonly vcs: VcsHandler
public readonly cache: TreeCache
Expand All @@ -162,7 +163,8 @@ export class Garden {
constructor(
public readonly projectRoot: string,
public readonly projectName: string,
public readonly environment: Environment,
environmentName: string,
variables: PrimitiveMap,
public readonly projectSources: SourceConfig[] = [],
public readonly buildDir: BuildDir,
log?: LogEntry,
Expand All @@ -186,6 +188,13 @@ export class Garden {
this.localConfigStore = new LocalConfigStore(this.projectRoot)
this.cache = new TreeCache()

this.environment = {
name: environmentName,
// The providers are populated when adding plugins in the factory.
providers: [],
variables,
}

this.moduleConfigs = {}
this.serviceNameIndex = {}
this.taskNameIndex = {}
Expand Down Expand Up @@ -269,25 +278,21 @@ export class Garden {

const fixedProviders = fixedPlugins.map(name => ({ name }))

const mergedProviders = merge(
const mergedProviderConfigs = merge(
fixedProviders,
keyBy(environmentDefaults.providers, "name"),
keyBy(environmentConfig.providers, "name"),
)

// Resolve the project configuration based on selected environment
const environment: Environment = {
name: environmentConfig.name,
providers: Object.values(mergedProviders),
variables: merge({}, environmentDefaults.variables, environmentConfig.variables),
}
const variables = merge({}, environmentDefaults.variables, environmentConfig.variables)

const buildDir = await BuildDir.factory(projectRoot)

const garden = new Garden(
projectRoot,
projectName,
environment,
environmentName,
variables,
projectSources,
buildDir,
log,
Expand All @@ -300,7 +305,7 @@ export class Garden {

// Load configured plugins
// Validate configuration
for (const provider of environment.providers) {
for (const provider of Object.values(mergedProviderConfigs)) {
await garden.loadPlugin(provider.name, provider)
}

Expand Down Expand Up @@ -423,7 +428,12 @@ export class Garden {
if (providerConfig) {
extend(providerConfig, plugin.config, config)
} else {
this.environment.providers.push(extend({ name: pluginName }, plugin.config, config))
const provider: Provider = {
name: pluginName,
dashboardPages: plugin.dashboardPages,
config: extend({ name: pluginName }, plugin.config, config),
}
this.environment.providers.push(provider)
}

for (const modulePath of plugin.modules || []) {
Expand Down
7 changes: 4 additions & 3 deletions garden-service/src/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import { Garden } from "./garden"
import { mapValues, keyBy, cloneDeep } from "lodash"
import { keyBy, cloneDeep } from "lodash"
import * as Joi from "joi"
import {
Provider,
Expand All @@ -19,6 +19,7 @@ import {
import { joiIdentifier, joiIdentifierMap } from "./config/common"
import { PluginError } from "./exceptions"
import { defaultProvider } from "./config/project"
import { dashboardPagesSchema } from "./config/dashboard"

type WrappedFromGarden = Pick<Garden,
"projectName" |
Expand All @@ -34,6 +35,7 @@ const providerSchema = Joi.object()
.keys({
name: joiIdentifier()
.description("The name of the provider (plugin)."),
dashboardPages: dashboardPagesSchema,
config: providerConfigBaseSchema,
})

Expand Down Expand Up @@ -63,8 +65,7 @@ export const pluginContextSchema = Joi.object()

export function createPluginContext(garden: Garden, providerName: string): PluginContext {
const projectConfig = cloneDeep(garden.environment)
const providerConfigs = keyBy(projectConfig.providers, "name")
const providers = mapValues(providerConfigs, (config, name) => ({ name, config }))
const providers = keyBy(projectConfig.providers, "name")
let provider = providers[providerName]

if (providerName === "_default") {
Expand Down
5 changes: 5 additions & 0 deletions garden-service/src/types/plugin/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { serviceStatusSchema } from "../service"
import { serviceOutputsSchema } from "../../config/service"
import { LogNode } from "../../logger/log-node"
import { Provider } from "../../config/project"
import { dashboardPagesSchema, DashboardPage } from "../../config/dashboard"
import {
ModuleActionParams,
PluginActionParams,
Expand Down Expand Up @@ -413,6 +414,9 @@ export interface GardenPlugin {

modules?: string[]

// TODO: move this to the configureProvider output, once that's implemented
dashboardPages?: DashboardPage[]

actions?: Partial<PluginActions>
moduleActions?: { [moduleType: string]: Partial<ModuleAndRuntimeActions> }
}
Expand All @@ -439,6 +443,7 @@ export const pluginSchema = Joi.object()
"Plugins may use this key to override or augment their configuration " +
"(as specified in the garden.yml provider configuration.",
),
dashboardPages: dashboardPagesSchema,
modules: joiArray(Joi.string())
.description(
"Plugins may optionally provide paths to Garden modules that are loaded as part of the plugin. " +
Expand Down
14 changes: 7 additions & 7 deletions garden-service/test/src/garden.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ describe("Garden", () => {
expect(garden.environment).to.eql({
name: "local",
providers: [
{ name: "generic" },
{ name: "container" },
{ name: "test-plugin" },
{ name: "test-plugin-b" },
{ name: "generic", dashboardPages: [], config: { name: "generic" } },
{ name: "container", dashboardPages: [], config: { name: "container" } },
{ name: "test-plugin", dashboardPages: [], config: { name: "test-plugin" } },
{ name: "test-plugin-b", dashboardPages: [], config: { name: "test-plugin-b" } },
],
variables: {
some: "variable",
Expand All @@ -77,9 +77,9 @@ describe("Garden", () => {
expect(garden.environment).to.eql({
name: "local",
providers: [
{ name: "generic" },
{ name: "container" },
{ name: "test-plugin" },
{ name: "generic", dashboardPages: [], config: { name: "generic" } },
{ name: "container", dashboardPages: [], config: { name: "container" } },
{ name: "test-plugin", dashboardPages: [], config: { name: "test-plugin" } },
],
variables: {
"some": "banana",
Expand Down

0 comments on commit c67b7be

Please sign in to comment.