Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multiple organizations #74

Merged
merged 1 commit into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions charts/clowarden/templates/server_secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,10 @@ stringData:
password: {{ .Values.server.basicAuth.password }}
githubApp:
appId: {{ .Values.server.githubApp.appId }}
installationId: {{ .Values.server.githubApp.installationId }}
privateKey: {{ .Values.server.githubApp.privateKey | quote }}
webhookSecret: {{ .Values.server.githubApp.webhookSecret | quote }}
config:
organization: {{ .Values.server.config.organization }}
repository: {{ .Values.server.config.repository }}
branch: {{ .Values.server.config.branch }}
legacy:
enabled: {{ .Values.server.config.legacy.enabled }}
sheriff:
permissionsPath: {{ .Values.server.config.legacy.sheriff.permissionsPath }}
{{- with .Values.server.config.legacy.cncf.peoplePath }}
cncf:
peoplePath: {{ . }}
{{- end }}
services:
github:
enabled: {{ .Values.server.config.services.github.enabled }}
services:
github:
enabled: {{ .Values.services.github.enabled }}
organizations: {{ toYaml .Values.organizations | nindent 6 }}

40 changes: 23 additions & 17 deletions charts/clowarden/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,11 @@ server:
githubApp:
# GitHub application ID
appId: null
# GitHub application installation ID
installationId: null
# GitHub application private key path
privateKey: null
# GitHub application webhook secret
webhookSecret: null

# CLOWarden service configuration
config:
organization: null
repository: null
branch: main
legacy:
enabled: true
sheriff:
permissionsPath: config.yaml
cncf:
peoplePath: null
services:
github:
enabled: true

# Ingress configuration
ingress:
enabled: true
Expand All @@ -101,6 +84,29 @@ server:
repository: clowarden-server
resources: {}

# Services CLOWarden will manage
services:
github:
enabled: true

# Organizations managed by this CLOWarden instance
organizations:
[]
# - # Name of the GitHub organization
# name: org-name
# # CLOWarden's GitHub application installation id
# installationId: 12345678
# # Repository where the configuration files are located
# repository: .clowarden
# # Branch to use in the configuration repository
# branch: main
# # Legacy mode configuration
# legacy:
# # Whether legacy mode is enabled or not
# enabled: true
# # Path of the Sheriff's permissions file
# sheriffPermissionsPath: config.yaml

# PostgreSQL configuration
postgresql:
enabled: true
Expand Down
89 changes: 60 additions & 29 deletions clowarden-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::doc_markdown, clippy::similar_names)]

use anyhow::{format_err, Result};
use clap::{Args, Parser, Subcommand};
use clowarden_core::{
github::GHApi,
cfg::Legacy,
github::{GHApi, Source},
multierror,
services::{
self,
github::{self, service::SvcApi, State},
github::{
self,
service::{Ctx, SvcApi},
State,
},
Change,
},
};
use config::Config;
use std::{env, sync::Arc};

#[derive(Parser)]
Expand Down Expand Up @@ -68,7 +75,7 @@ async fn main() -> Result<()> {

// Setup logging
if std::env::var_os("RUST_LOG").is_none() {
std::env::set_var("RUST_LOG", "clowarden_cli=debug")
std::env::set_var("RUST_LOG", "clowarden_cli=debug");
}
tracing_subscriber::fmt::init();

Expand All @@ -91,10 +98,15 @@ async fn main() -> Result<()> {
async fn validate(args: BaseArgs, github_token: String) -> Result<()> {
// GitHub

// Setup services
let (gh, svc) = setup_services(github_token);
let legacy = setup_legacy(&args);
let ctx = setup_context(&args);
let src = setup_source(&args);

// Validate configuration and display results
println!("Validating configuration...");
let (cfg, gh, svc) = setup_services(&args, github_token)?;
match github::State::new_from_config(cfg, gh, svc, None, None, None).await {
match github::State::new_from_config(gh, svc, &legacy, &ctx, &src).await {
Ok(_) => println!("Configuration is valid!"),
Err(err) => {
println!("{}\n", multierror::format_error(&err)?);
Expand All @@ -109,21 +121,26 @@ async fn validate(args: BaseArgs, github_token: String) -> Result<()> {
async fn diff(args: BaseArgs, github_token: String) -> Result<()> {
// GitHub

// Setup services
let (gh, svc) = setup_services(github_token);
let legacy = setup_legacy(&args);
let ctx = setup_context(&args);
let src = setup_source(&args);

// Get changes from the actual state to the desired state
println!("Calculating diff between the actual state and the desired state...");
let (cfg, gh, svc) = setup_services(&args, github_token)?;
let actual_state = State::new_from_service(svc.clone()).await?;
let desired_state = State::new_from_config(cfg, gh, svc, None, None, None).await?;
let actual_state = State::new_from_service(svc.clone(), &ctx).await?;
let desired_state = State::new_from_config(gh, svc, &legacy, &ctx, &src).await?;
let changes = actual_state.diff(&desired_state);

// Display changes
println!("\n# GitHub");
println!("\n## Directory changes\n");
for change in changes.directory.into_iter() {
for change in changes.directory {
println!("{}", change.template_format()?);
}
println!("\n## Repositories changes\n");
for change in changes.repositories.into_iter() {
for change in changes.repositories {
println!("{}", change.template_format()?);
}
println!();
Expand All @@ -132,22 +149,36 @@ async fn diff(args: BaseArgs, github_token: String) -> Result<()> {
}

/// Helper function to setup some services from the arguments provided.
fn setup_services(args: &BaseArgs, github_token: String) -> Result<(Arc<Config>, Arc<GHApi>, Arc<SvcApi>)> {
let cfg = Config::builder()
.set_override("server.config.legacy.enabled", true)?
.set_override(
"server.config.legacy.sheriff.permissionsPath",
args.permissions_file.clone(),
)?
.set_override_option("server.config.legacy.cncf.peoplePath", args.people_file.clone())?
.build()?;
let gh = GHApi::new(
args.org.clone(),
args.repo.clone(),
args.branch.clone(),
github_token.clone(),
)?;
let svc = services::github::service::SvcApi::new(args.org.clone(), github_token)?;

Ok((Arc::new(cfg), Arc::new(gh), Arc::new(svc)))
fn setup_services(github_token: String) -> (Arc<GHApi>, Arc<SvcApi>) {
let gh = GHApi::new_with_token(github_token.clone());
let svc = services::github::service::SvcApi::new_with_token(github_token);

(Arc::new(gh), Arc::new(svc))
}

/// Helper function to create a legacy config instance from the arguments.
fn setup_legacy(args: &BaseArgs) -> Legacy {
Legacy {
enabled: true,
sheriff_permissions_path: args.permissions_file.clone(),
cncf_people_path: args.people_file.clone(),
}
}

/// Helper function to create a context instance from the arguments.
fn setup_context(args: &BaseArgs) -> Ctx {
Ctx {
inst_id: None,
org: args.org.clone(),
}
}

/// Helper function to create a source instance from the arguments.
fn setup_source(args: &BaseArgs) -> Source {
Source {
inst_id: None,
owner: args.org.clone(),
repo: args.repo.clone(),
ref_: args.branch.clone(),
}
}
32 changes: 32 additions & 0 deletions clowarden-core/src/cfg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! This module defines some types that represent parts of the configuration.

use serde::{Deserialize, Serialize};

/// Organization configuration.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Organization {
pub name: String,
pub installation_id: i64,
pub repository: String,
pub branch: String,
pub legacy: Legacy,
}

/// Organization legacy configuration.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct Legacy {
pub enabled: bool,
pub sheriff_permissions_path: String,
pub cncf_people_path: Option<String>,
}

/// GitHub application configuration.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all(deserialize = "camelCase"))]
pub struct GitHubApp {
pub app_id: i64,
pub private_key: String,
pub webhook_secret: String,
}
Loading
Loading