forked from hswaw/hscloud
Merge remote-tracking branch 'origin/master'
Change-Id: I31065ed4d5ab138a90e0be79a9d00db155896eccmaster
commit
924be126f7
2
.bazelrc
2
.bazelrc
|
@ -6,3 +6,5 @@ build --stamp
|
|||
build --workspace_status_command=./bzl/workspace-status.sh
|
||||
test --build_tests_only
|
||||
test --test_output=errors
|
||||
build --cxxopt=-std=c++14
|
||||
build --host_cxxopt=-std=c++14
|
||||
|
|
|
@ -1 +1 @@
|
|||
5.2.0
|
||||
5.4.1
|
||||
|
|
15
BUILD
15
BUILD
|
@ -2,15 +2,24 @@
|
|||
load("@bazel_gazelle//:def.bzl", "gazelle")
|
||||
|
||||
# Used by //go/workspace tests.
|
||||
exports_files(["WORKSPACE", "default.nix"])
|
||||
exports_files([
|
||||
"WORKSPACE",
|
||||
"default.nix",
|
||||
])
|
||||
|
||||
# gazelle:prefix code.hackerspace.pl/hscloud
|
||||
# gazelle:go_naming_convention go_default_library
|
||||
# gazelle:go_naming_convention import
|
||||
# gazelle:exclude **/gomod-generated-placeholder.go
|
||||
gazelle(name = "gazelle")
|
||||
|
||||
gazelle(
|
||||
name = "gazelle",
|
||||
name = "gazelle-update-repos",
|
||||
args = [
|
||||
"-from_file=go.mod",
|
||||
"-to_macro=third_party/go/repositories.bzl%go_repositories",
|
||||
"-prune",
|
||||
],
|
||||
command = "update-repos",
|
||||
)
|
||||
|
||||
config_setting(
|
||||
|
|
258
WORKSPACE
258
WORKSPACE
|
@ -2,50 +2,15 @@ workspace(
|
|||
name = "hscloud",
|
||||
)
|
||||
|
||||
local_repository(
|
||||
name = "rules_jvm_external",
|
||||
path = "/home/q3k/Software/rules_jvm_external",
|
||||
)
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
|
||||
|
||||
# Protobuf deps (shared between many rules).
|
||||
# Load this as early as possible, to avoid a different version being pulled in by deps of something else
|
||||
http_archive(
|
||||
name = "com_google_protobuf",
|
||||
sha256 = "8b28fdd45bab62d15db232ec404248901842e5340299a57765e48abe8a80d930",
|
||||
strip_prefix = "protobuf-3.20.1",
|
||||
urls = ["https://github.com/google/protobuf/archive/v3.20.1.tar.gz"],
|
||||
)
|
||||
|
||||
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
|
||||
|
||||
protobuf_deps()
|
||||
|
||||
rules_python_version = "0.13.0"
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "8c8fe44ef0a9afc256d1e75ad5f448bb59b81aba149b8958f02f7b3a98f5d9b4",
|
||||
strip_prefix = "rules_python-{}".format(rules_python_version),
|
||||
url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/{}.tar.gz".format(rules_python_version),
|
||||
)
|
||||
|
||||
# Download Go/Gazelle rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "099a9fb96a376ccbbb7d291ed4ecbdfd42f6bc822ab77ae6f1b5cb9e914e94fa",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
sha256 = "448e37e0dbf61d6fa8f00aaa12d191745e14f07c31cabfa731f0c8e8a4f41b97",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
# Gazelle started requiring this after we bumped the version to v0.28.0.
|
||||
# Load skylib
|
||||
http_archive(
|
||||
name = "bazel_skylib",
|
||||
sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
|
||||
|
@ -59,6 +24,67 @@ load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
|
|||
|
||||
bazel_skylib_workspace()
|
||||
|
||||
load("@bazel_skylib//lib:versions.bzl", "versions")
|
||||
|
||||
versions.check(minimum_bazel_version = "5.4.1")
|
||||
|
||||
# Protobuf deps (shared between many rules).
|
||||
# Load this as early as possible, to avoid a different version being pulled in by deps of something else
|
||||
http_archive(
|
||||
name = "com_google_protobuf",
|
||||
sha256 = "76a33e2136f23971ce46c72fd697cd94dc9f73d56ab23b753c3e16854c90ddfd",
|
||||
strip_prefix = "protobuf-2c5fa078d8e86e5f4bd34e6f4c9ea9e8d7d4d44a",
|
||||
urls = [
|
||||
"https://github.com/protocolbuffers/protobuf/archive/2c5fa078d8e86e5f4bd34e6f4c9ea9e8d7d4d44a.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_proto",
|
||||
sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd",
|
||||
strip_prefix = "rules_proto-5.3.0-21.7",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
|
||||
|
||||
rules_proto_dependencies()
|
||||
|
||||
rules_proto_toolchains()
|
||||
|
||||
rules_python_version = "0.24.0"
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "0a8003b044294d7840ac7d9d73eef05d6ceb682d7516781a4ec62eeb34702578",
|
||||
strip_prefix = "rules_python-{}".format(rules_python_version),
|
||||
url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/{}.tar.gz".format(rules_python_version),
|
||||
)
|
||||
|
||||
# Download Go/Gazelle rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "51dc53293afe317d2696d4d6433a4c33feedb7748a9e352072e2ec3c0dafd2c6",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.40.1/rules_go-v0.40.1.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.40.1/rules_go-v0.40.1.zip",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
sha256 = "29d5dafc2a5582995488c6735115d1d366fcd6a0fc2e2a153f02988706349825",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.31.0/bazel-gazelle-v0.31.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.31.0/bazel-gazelle-v0.31.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
load("//third_party/go:repositories.bzl", "go_repositories")
|
||||
|
||||
# Python rules
|
||||
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
|
||||
|
||||
|
@ -77,19 +103,38 @@ pip_parse(
|
|||
)
|
||||
|
||||
load("@pydeps//:requirements.bzl", "install_deps")
|
||||
|
||||
install_deps()
|
||||
|
||||
# Setup Go toolchain.
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains")
|
||||
|
||||
go_register_toolchains(version = "1.18.3")
|
||||
# gazelle:repository_macro third_party/go/repositories.bzl%go_repositories
|
||||
# gazelle:repository go_repository name=hscloud importpath=code.hackerspace.pl/hscloud
|
||||
go_repositories()
|
||||
|
||||
load("@bazel_gazelle//:deps.bzl", "go_repository")
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_mod",
|
||||
build_external = "external",
|
||||
importpath = "golang.org/x/mod",
|
||||
sum = "h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=",
|
||||
version = "v0.10.0",
|
||||
)
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(go_version = "1.20.5")
|
||||
|
||||
# IMPORTANT: match protobuf version above with the one loaded by grpc
|
||||
http_archive(
|
||||
name = "com_github_grpc_grpc",
|
||||
sha256 = "419dba362eaf8f1d36849ceee17c3e2ff8ff12ac666b42d3ff02a164ebe090e9",
|
||||
strip_prefix = "grpc-1.30.0",
|
||||
urls = ["https://github.com/grpc/grpc/archive/v1.30.0.tar.gz"],
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
"//third_party:grpc_extra_deps.patch",
|
||||
],
|
||||
sha256 = "931f07db9d48cff6a6007c1033ba6d691fe655bea2765444bc1ad974dfc840aa",
|
||||
strip_prefix = "grpc-1.56.2",
|
||||
urls = ["https://github.com/grpc/grpc/archive/v1.56.2.tar.gz"],
|
||||
)
|
||||
|
||||
# Load grpc deps after Go, to prevent overriding Go toolchains/SDK.
|
||||
|
@ -101,48 +146,20 @@ load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
|
|||
|
||||
grpc_extra_deps()
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
# gazelle:repository_macro third_party/go/repositories.bzl%go_repositories
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
|
||||
|
||||
# Force newer version of golang.org/x/crypto that gazelle_dependencies would
|
||||
# usually get.
|
||||
go_repository(
|
||||
name = "org_golang_x_crypto",
|
||||
build_naming_convention = "go_default_library",
|
||||
importpath = "golang.org/x/crypto",
|
||||
sum = "h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=",
|
||||
version = "v0.0.0-20210921155107-089bfa567519",
|
||||
)
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
|
||||
|
||||
gazelle_dependencies()
|
||||
|
||||
# Load Go third-party packages.
|
||||
load("//third_party/go:repositories.bzl", "go_repositories")
|
||||
|
||||
go_repositories()
|
||||
|
||||
# Docker rules
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_docker",
|
||||
sha256 = "4349f2b0b45c860dd2ffe18802e9f79183806af93ce5921fb12cbd6c07ab69a8",
|
||||
strip_prefix = "rules_docker-0.21.0",
|
||||
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.21.0/rules_docker-v0.21.0.tar.gz"],
|
||||
sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf",
|
||||
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"],
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_docker//toolchains/docker:toolchain.bzl", docker_toolchain_configure = "toolchain_configure")
|
||||
|
||||
# This forces the use of Docker $HOME/.docker configuration.
|
||||
docker_toolchain_configure(
|
||||
name = "docker_config",
|
||||
client_config = "",
|
||||
docker_path = "/usr/bin/docker",
|
||||
)
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_docker//repositories:repositories.bzl",
|
||||
container_repositories = "repositories",
|
||||
|
@ -150,10 +167,26 @@ load(
|
|||
|
||||
container_repositories()
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_docker//python3:image.bzl",
|
||||
_py_image_repos = "repositories",
|
||||
)
|
||||
|
||||
_py_image_repos()
|
||||
|
||||
# Docker base images
|
||||
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_pull")
|
||||
|
||||
container_pull(
|
||||
name = "python-debian",
|
||||
digest = "sha256:cfa3b79333c4e56fc675b6800445b6dcbb3e6cd4d52f2a9ade944ab73dadc6a1",
|
||||
registry = "index.docker.io",
|
||||
repository = "python",
|
||||
tag = "3.10-bullseye", # use the same version as in python_register_toolchains
|
||||
)
|
||||
|
||||
|
||||
container_pull(
|
||||
name = "prodimage-bionic",
|
||||
digest = "sha256:1cd1f84169b8e1414a5d511b42909f2d540831c67b6799ae9af8cd6a80d75b5f",
|
||||
|
@ -190,6 +223,10 @@ git_repository(
|
|||
commit = "a511f3c90129d7de7ae67c0637001162980c08d5",
|
||||
remote = "https://gerrit.googlesource.com/bazlets",
|
||||
shallow_since = "1606931369 -0600",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
"//third_party:bazlets_py3.patch",
|
||||
],
|
||||
)
|
||||
|
||||
load("@com_googlesource_gerrit_bazlets//:gerrit_api.bzl", "gerrit_api")
|
||||
|
@ -220,59 +257,6 @@ http_file(
|
|||
],
|
||||
)
|
||||
|
||||
# minecraft spigot/bukkit deps
|
||||
# this uses rules_jvm_external vs gerrit's maven_jar because we need SNAPSHOT support
|
||||
|
||||
http_archive(
|
||||
name = "io_grpc_grpc_java",
|
||||
sha256 = "446ad7a2e85bbd05406dbf95232c7c49ed90de83b3b60cb2048b0c4c9f254d29",
|
||||
strip_prefix = "grpc-java-1.29.0",
|
||||
url = "https://github.com/grpc/grpc-java/archive/v1.29.0.zip",
|
||||
)
|
||||
|
||||
RULES_JVM_EXTERNAL_TAG = "3.0"
|
||||
|
||||
RULES_JVM_EXTERNAL_SHA = "62133c125bf4109dfd9d2af64830208356ce4ef8b165a6ef15bbff7460b35c3a"
|
||||
|
||||
http_archive(
|
||||
name = "rules_jvm_external",
|
||||
sha256 = RULES_JVM_EXTERNAL_SHA,
|
||||
strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
|
||||
url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
|
||||
)
|
||||
|
||||
load("@rules_jvm_external//:defs.bzl", "maven_install")
|
||||
load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_ARTIFACTS")
|
||||
load("@io_grpc_grpc_java//:repositories.bzl", "IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS")
|
||||
|
||||
maven_install(
|
||||
artifacts = [
|
||||
"org.spigotmc:spigot-api:1.15.2-R0.1-20200624.001023-124",
|
||||
"io.grpc:grpc-netty-shaded:1.29.0",
|
||||
"io.grpc:grpc-services:1.29.0",
|
||||
] + IO_GRPC_GRPC_JAVA_ARTIFACTS,
|
||||
generate_compat_repositories = True,
|
||||
maven_install_json = "//third_party/java:maven_install.json",
|
||||
override_targets = IO_GRPC_GRPC_JAVA_OVERRIDE_TARGETS,
|
||||
repositories = [
|
||||
"https://hub.spigotmc.org/nexus/content/repositories/snapshots",
|
||||
"https://oss.sonatype.org/content/repositories/snapshots",
|
||||
"https://repo1.maven.org/maven2/",
|
||||
],
|
||||
)
|
||||
|
||||
load("@maven//:defs.bzl", "pinned_maven_install")
|
||||
|
||||
pinned_maven_install()
|
||||
|
||||
load("@maven//:compat.bzl", "compat_repositories")
|
||||
|
||||
compat_repositories()
|
||||
|
||||
load("@io_grpc_grpc_java//:repositories.bzl", "grpc_java_repositories")
|
||||
|
||||
grpc_java_repositories()
|
||||
|
||||
# Gerrit OWNERS plugins external repositories
|
||||
|
||||
git_repository(
|
||||
|
@ -288,12 +272,16 @@ gerrit_owners_deps()
|
|||
|
||||
# Go image repos for Docker
|
||||
|
||||
load("@io_bazel_rules_docker//go:image.bzl", go_image_repositories = "repositories")
|
||||
load(
|
||||
"@io_bazel_rules_docker//go:image.bzl",
|
||||
go_image_repos = "repositories",
|
||||
)
|
||||
|
||||
go_image_repositories()
|
||||
go_image_repos()
|
||||
|
||||
# //hswaw/site deps.
|
||||
load("//hswaw/site:deps.bzl", "hswaw_site_deps")
|
||||
|
||||
hswaw_site_deps()
|
||||
|
||||
# noVNC, used by //dc/drackvm.
|
||||
|
@ -321,7 +309,7 @@ filegroup(
|
|||
http_file(
|
||||
name = "calicoctl_3_15",
|
||||
downloaded_file_path = "calicoctl",
|
||||
urls = ["https://github.com/projectcalico/calicoctl/releases/download/v3.15.5/calicoctl"],
|
||||
sha256 = "f49e9e8d25108f7f22d5a51c756b2fe40cbe36347ad297e31a767376172f2845",
|
||||
executable = True,
|
||||
sha256 = "f49e9e8d25108f7f22d5a51c756b2fe40cbe36347ad297e31a767376172f2845",
|
||||
urls = ["https://github.com/projectcalico/calicoctl/releases/download/v3.15.5/calicoctl"],
|
||||
)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# inventory
|
||||
|
||||
For app source, see https://code.hackerspace.pl/informatic/spejstore
|
|
@ -0,0 +1,119 @@
|
|||
local kube = import '../../kube/kube.libsonnet';
|
||||
local postgres = import '../../kube/postgres_v.libsonnet';
|
||||
|
||||
{
|
||||
local top = self,
|
||||
local cfg = top.cfg,
|
||||
|
||||
cfg:: {
|
||||
name: 'inventory',
|
||||
namespace: 'inventory',
|
||||
domain: 'inventory.hackerspace.pl',
|
||||
|
||||
image: 'registry.k0.hswaw.net/palid/spejstore:1694280421',
|
||||
db: {
|
||||
name: 'inventory',
|
||||
username: 'inventory',
|
||||
},
|
||||
oauthClientId: '82fffb65-0bbd-4d18-becd-0ce0b31373cf',
|
||||
storageClassName: 'waw-hdd-redundant-3',
|
||||
|
||||
mediaPath: '/var/www/media',
|
||||
},
|
||||
|
||||
secrets:: {
|
||||
postgres: { secretKeyRef: { name: cfg.name, key: 'postgres_password' } },
|
||||
oauth: { secretKeyRef: { name: cfg.name, key: 'oauth_secret' } },
|
||||
},
|
||||
|
||||
ns: kube.Namespace(cfg.namespace),
|
||||
deployment: top.ns.Contain(kube.Deployment(cfg.name)) {
|
||||
spec+: {
|
||||
template+: {
|
||||
spec+: {
|
||||
volumes_: {
|
||||
media: kube.PersistentVolumeClaimVolume(top.media),
|
||||
},
|
||||
containers_: {
|
||||
default: kube.Container('default') {
|
||||
image: cfg.image,
|
||||
ports_: {
|
||||
web: { containerPort: 8000 },
|
||||
},
|
||||
env_: {
|
||||
SPEJSTORE_ENV: 'prod',
|
||||
SPEJSTORE_DB_NAME: cfg.db.name,
|
||||
SPEJSTORE_DB_USER: cfg.db.username,
|
||||
SPEJSTORE_DB_PASSWORD: top.secrets.postgres,
|
||||
SPEJSTORE_DB_HOST: top.psql.svc.host,
|
||||
SPEJSTORE_DB_PORT: top.psql.svc.port,
|
||||
SPEJSTORE_ALLOWED_HOSTS: cfg.domain,
|
||||
SPEJSTORE_CLIENT_ID: cfg.oauthClientId,
|
||||
SPEJSTORE_SECRET: top.secrets.oauth,
|
||||
SPEJSTORE_MEDIA_ROOT: cfg.mediaPath,
|
||||
SPEJSTORE_REQUIRE_AUTH: 'true',
|
||||
SPEJSTORE_LAN_ALLOWED_ADDRESS_SPACE: '185.236.240.5',
|
||||
},
|
||||
volumeMounts_: {
|
||||
media: { mountPath: cfg.mediaPath },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
media: top.ns.Contain(kube.PersistentVolumeClaim(cfg.name)) {
|
||||
spec+: {
|
||||
storageClassName: cfg.storageClassName,
|
||||
accessModes: ['ReadWriteOnce'],
|
||||
resources: {
|
||||
requests: {
|
||||
storage: '20Gi',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
psql: postgres {
|
||||
cfg+: {
|
||||
namespace: cfg.namespace,
|
||||
appName: cfg.name,
|
||||
storageClassName: cfg.storageClassName,
|
||||
version: '15.4',
|
||||
|
||||
database: cfg.db.name,
|
||||
username: cfg.db.username,
|
||||
password: top.secrets.postgres,
|
||||
},
|
||||
bouncer: {},
|
||||
},
|
||||
|
||||
service: top.ns.Contain(kube.Service(cfg.name)) {
|
||||
target_pod:: top.deployment.spec.template,
|
||||
},
|
||||
|
||||
ingress: top.ns.Contain(kube.Ingress(cfg.name)) {
|
||||
metadata+: {
|
||||
annotations+: {
|
||||
'kubernetes.io/tls-acme': 'true',
|
||||
'cert-manager.io/cluster-issuer': 'letsencrypt-prod',
|
||||
'nginx.ingress.kubernetes.io/proxy-body-size': '0',
|
||||
},
|
||||
},
|
||||
spec+: {
|
||||
tls: [{ hosts: [cfg.domain], secretName: cfg.name + '-tls' }],
|
||||
rules: [
|
||||
{
|
||||
host: cfg.domain,
|
||||
http: {
|
||||
paths: [
|
||||
{ path: '/', backend: top.service.name_port },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
load("@pydeps//:requirements.bzl", "requirement")
|
||||
load("@rules_python//python:defs.bzl", "py_binary")
|
||||
load("@io_bazel_rules_docker//python:image.bzl", "py_layer")
|
||||
load("@io_bazel_rules_docker//python3:image.bzl", "py3_image")
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_layer", "container_image")
|
||||
load("@io_bazel_rules_docker//docker/util:run.bzl", "container_run_and_extract", "container_run_and_commit_layer")
|
||||
load("@io_bazel_rules_docker//docker/package_managers:download_pkgs.bzl", "download_pkgs")
|
||||
load("@io_bazel_rules_docker//docker/package_managers:install_pkgs.bzl", "install_pkgs")
|
||||
|
||||
# - - base docker stuff - -
|
||||
|
||||
download_pkgs(
|
||||
name = "apt_py_is_py3",
|
||||
image_tar = "@python-debian//image",
|
||||
packages = [
|
||||
# rules_docker python wants /usr/bin/python
|
||||
"python-is-python3",
|
||||
],
|
||||
)
|
||||
|
||||
install_pkgs(
|
||||
name = "base_image",
|
||||
output_image_name = "base_image",
|
||||
image_tar = "@python-debian//image",
|
||||
installables_tar = ":apt_py_is_py3.tar",
|
||||
installation_cleanup_commands = "rm -rf /var/lib/apt/lists/* /usr/share/doc && apt remove -y libbluetooth3 mariadb-common tk && apt autoremove -y",
|
||||
)
|
||||
|
||||
BASE_IMAGE = ":base_image"
|
||||
|
||||
# overkill rube goldberg setup to build static files begins
|
||||
# - - - -
|
||||
|
||||
container_run_and_extract(
|
||||
name = "static_pack",
|
||||
commands = [
|
||||
"tar cpJvf /out.tar.xz -C /opt/mailman/web/static ./",
|
||||
],
|
||||
extract_file = "/out.tar.xz",
|
||||
image = ":static_build_image.tar",
|
||||
)
|
||||
|
||||
container_image(
|
||||
name = "static_build_image",
|
||||
layers = [":static_build_layer"],
|
||||
base = BASE_IMAGE,
|
||||
)
|
||||
|
||||
# this will also contain .pyc files, but the python binary will be the same
|
||||
# on prod, so it's fine
|
||||
container_run_and_commit_layer(
|
||||
name = "static_build_layer",
|
||||
commands = [
|
||||
"./app/mailman-web/manage collectstatic",
|
||||
"./app/mailman-web/manage compress",
|
||||
# gettext is cursed, TODO make this work
|
||||
#"./app/mailman-web/manage compilemessages",
|
||||
],
|
||||
image = ":build_container.tar",
|
||||
docker_run_flags = ["--entrypoint="],
|
||||
)
|
||||
|
||||
py3_image(
|
||||
name = "build_container",
|
||||
srcs = [":manage"],
|
||||
main = "manage.py",
|
||||
base = ":build_tools_container",
|
||||
layers = [":deps_layer"],
|
||||
# this doesn't work for some reason - this is always rebuilt, unless
|
||||
# you pass --nostamp globally
|
||||
stamp = 0,
|
||||
)
|
||||
|
||||
download_pkgs(
|
||||
name = "build_tools",
|
||||
image_tar = "@python-debian//image",
|
||||
packages = [
|
||||
"sassc",
|
||||
"gettext",
|
||||
],
|
||||
)
|
||||
|
||||
install_pkgs(
|
||||
name = "build_tools_container",
|
||||
output_image_name = "build_tools_container",
|
||||
image_tar = BASE_IMAGE + '.tar',
|
||||
installables_tar = ":build_tools.tar",
|
||||
installation_cleanup_commands = "rm -rf /var/lib/apt/lists/* /usr/share/doc",
|
||||
)
|
||||
|
||||
# - - - -
|
||||
# overkill rube goldberg setup to build static files ends
|
||||
|
||||
|
||||
# - - python stuff - -
|
||||
|
||||
# this is purely a build optimization - put the pip deps into a separate layer
|
||||
py_layer(
|
||||
name = "deps_layer",
|
||||
deps = [
|
||||
requirement("Django"),
|
||||
requirement("postorius"),
|
||||
requirement("hyperkitty"),
|
||||
requirement("gunicorn"),
|
||||
requirement("psycopg2-binary"),
|
||||
],
|
||||
)
|
||||
|
||||
py_library(
|
||||
name = "django_base",
|
||||
srcs = ["settings.py", "urls.py"]
|
||||
+ glob(["upstream_settings/*.py"]),
|
||||
deps = [
|
||||
requirement("Django"),
|
||||
requirement("postorius"),
|
||||
requirement("hyperkitty"),
|
||||
requirement("gunicorn"),
|
||||
requirement("psycopg2-binary"),
|
||||
],
|
||||
)
|
||||
|
||||
py_binary(
|
||||
name = "manage",
|
||||
srcs = ["manage.py"],
|
||||
deps = [":django_base"],
|
||||
)
|
||||
|
||||
py_binary(
|
||||
name = "serve",
|
||||
srcs = ["serve.py"],
|
||||
deps = [":django_base"],
|
||||
)
|
||||
|
||||
# prod docker image
|
||||
|
||||
py3_image(
|
||||
name = "mailman-web",
|
||||
srcs = ["container_main.py"],
|
||||
deps = [
|
||||
":django_base",
|
||||
":manage",
|
||||
":serve",
|
||||
],
|
||||
layers = [
|
||||
":deps_layer",
|
||||
],
|
||||
main = "container_main.py",
|
||||
#base = ":base_container"
|
||||
base = ":static_build_image",
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
Mailman and its components (postorius, hyperkitty) are licensed under GPLv3 and we link/import that code here directly.
|
||||
Also, a good portion of this wsgi launcher is copied from https://gitlab.com/mailman/mailman-web, GPLv3 as well.
|
||||
Therefore, this entire directory likely falls under GPLv3.
|
|
@ -0,0 +1,7 @@
|
|||
Web parts of mailman3 - postorius and hyperkitty.
|
||||
Postgres only, TODO attempt cockroachization.
|
||||
|
||||
This currently serves static files via an extremely cursed hack:
|
||||
lists.hackerspace.pl points to boston-packets, which serves /static/* from
|
||||
a local directory there, made by extracting :static_pack there; and proxy_passes
|
||||
every other path to the k8s Service defined here.
|
|
@ -0,0 +1,13 @@
|
|||
from sys import argv, exit
|
||||
|
||||
# simple wrapper so we don't need two container entrypoints
|
||||
assert len(argv) > 1, "specify a command"
|
||||
if argv[1] == "serve":
|
||||
import serve
|
||||
serve.main()
|
||||
elif argv[1] == "manage":
|
||||
import manage
|
||||
manage.main(argv[1:])
|
||||
else:
|
||||
print("unknown command", argv[1])
|
||||
exit(1)
|
|
@ -0,0 +1,215 @@
|
|||
local kube = import "../../../kube/kube.libsonnet";
|
||||
|
||||
{
|
||||
local app = self,
|
||||
local cfg = app.cfg,
|
||||
|
||||
cfg:: {
|
||||
namespace: error "cfg.namespace must be set",
|
||||
webDomain: error "cfg.webDomain must be set",
|
||||
images: {
|
||||
web: "registry.k0.hswaw.net/implr/mailman-web:0.6",
|
||||
# https://github.com/octeep/wireproxy
|
||||
wireproxy: "registry.k0.hswaw.net/implr/wireproxy:1.0.5"
|
||||
},
|
||||
passwords: {
|
||||
postgres: error "cfg.secrets.postgres must be set",
|
||||
mailmanRest: error "cfg.secrets.mailmanRest must be set",
|
||||
mailmanArchiver: error "cfg.secrets.mailmanArchiver must be set",
|
||||
},
|
||||
smtp: {
|
||||
user: "postorius",
|
||||
# from mail server
|
||||
password: error "cfg.smtp.password must be set",
|
||||
},
|
||||
secrets: {
|
||||
djangoSecretKey: error "cfg.secrets.djangoSecretKey must be set",
|
||||
},
|
||||
wg: {
|
||||
peerPubkey: error "cfg.wg.peerPubkey must be set",
|
||||
privkey: error "cfg.wg.privkey must be set",
|
||||
endpoint: error "cfg.wg.endpoint must be set",
|
||||
},
|
||||
},
|
||||
|
||||
env:: {
|
||||
WEB_DOMAIN: cfg.webDomain,
|
||||
BIND_ADDR: "0.0.0.0:8080",
|
||||
|
||||
//DB_HOST: app.postgres.svc.host,
|
||||
DB_HOST: "boston-packets.hackerspace.pl",
|
||||
DB_USER: "mailman",
|
||||
DB_NAME: "mailman-web",
|
||||
DB_PASS: kube.SecretKeyRef(app.config, "postgres-pass"),
|
||||
DB_PORT: "5432",
|
||||
|
||||
|
||||
SMTP_HOST: "mail.hackerspace.pl",
|
||||
SMTP_PORT: "587",
|
||||
SMTP_USER: "postorius",
|
||||
SMTP_PASSWORD: kube.SecretKeyRef(app.config, "smtp-password"),
|
||||
|
||||
SECRET_KEY: kube.SecretKeyRef(app.config, "django-secret-key"),
|
||||
MAILMAN_REST_API_PASS: kube.SecretKeyRef(app.config, 'mailman-api-password'),
|
||||
MAILMAN_ARCHIVER_KEY: kube.SecretKeyRef(app.config, 'mailman-archiver-key'),
|
||||
|
||||
},
|
||||
|
||||
namespace: kube.Namespace(cfg.namespace),
|
||||
local ns = self.namespace,
|
||||
|
||||
|
||||
web: ns.Contain(kube.Deployment("web")) {
|
||||
spec+: {
|
||||
minReadySeconds: 10,
|
||||
replicas: 1,
|
||||
template+: {
|
||||
spec+: {
|
||||
initContainers_: {
|
||||
migrate: kube.Container("migrate") {
|
||||
image: cfg.images.web,
|
||||
env_: app.env,
|
||||
args: [
|
||||
"manage", "migrate",
|
||||
],
|
||||
},
|
||||
},
|
||||
volumes_: {
|
||||
config: kube.SecretVolume(app.wireproxyConfig),
|
||||
},
|
||||
containers_: {
|
||||
default: kube.Container("default") {
|
||||
image: cfg.images.web,
|
||||
env_: app.env,
|
||||
args: ["serve"],
|
||||
ports_: {
|
||||
web: { containerPort: 8080 },
|
||||
},
|
||||
# readinessProbe: {
|
||||
# httpGet: {
|
||||
# path: "/",
|
||||
# port: "web",
|
||||
# },
|
||||
# failureThreshold: 10,
|
||||
# periodSeconds: 5,
|
||||
# },
|
||||
resources: {
|
||||
requests: {
|
||||
cpu: "250m",
|
||||
memory: "1024M",
|
||||
},
|
||||
limits: {
|
||||
cpu: "1",
|
||||
memory: "1024M",
|
||||
},
|
||||
},
|
||||
},
|
||||
wireproxy: kube.Container("wireproxy") {
|
||||
image: cfg.images.wireproxy,
|
||||
resources: {
|
||||
requests: {
|
||||
cpu: "100m",
|
||||
memory: "64M",
|
||||
},
|
||||
limits: {
|
||||
cpu: "200m",
|
||||
memory: "128M",
|
||||
},
|
||||
},
|
||||
volumeMounts_: {
|
||||
config: { mountPath: "/etc/wireproxy/config", subPath: "config" }
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
local manifestIniMultisection(sname, values) = std.join('\n',
|
||||
[std.manifestIni({
|
||||
sections: {
|
||||
[sname]: i,
|
||||
}}) for i in values]),
|
||||
wireproxyConfig: ns.Contain(kube.Secret("wireproxy-config")) {
|
||||
data: {
|
||||
config: std.base64(std.manifestIni({
|
||||
sections: {
|
||||
Interface: {
|
||||
Address: cfg.wg.address,
|
||||
PrivateKey: cfg.wg.privkey,
|
||||
},
|
||||
Peer: {
|
||||
PublicKey: cfg.wg.peerPubkey,
|
||||
Endpoint: cfg.wg.endpoint,
|
||||
},
|
||||
|
||||
},
|
||||
}) + manifestIniMultisection("TCPClientTunnel", [
|
||||
# {
|
||||
# # postgres
|
||||
# ListenPort: 5432,
|
||||
# Target: "localhost:5432",
|
||||
# },
|
||||
{
|
||||
# mailman core api
|
||||
BindAddress: "127.0.0.1:8001",
|
||||
Target: "172.17.1.1:8001",
|
||||
},
|
||||
])),
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
svcWeb: ns.Contain(kube.Service("web")) {
|
||||
target_pod: app.web.spec.template,
|
||||
spec+: {
|
||||
# hax
|
||||
type: "LoadBalancer",
|
||||
externalTrafficPolicy: "Local",
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
#ingress: ns.Contain(kube.Ingress("mailman")) {
|
||||
# metadata+: {
|
||||
# annotations+: {
|
||||
# "kubernetes.io/tls-acme": "true",
|
||||
# "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
|
||||
# "nginx.ingress.kubernetes.io/proxy-body-size": "0",
|
||||
# },
|
||||
# },
|
||||
# spec+: {
|
||||
# tls: [
|
||||
# {
|
||||
# hosts: [cfg.webDomain],
|
||||
# secretName: "mailman-ingress-tls",
|
||||
# },
|
||||
# ],
|
||||
# rules: [
|
||||
# {
|
||||
# host: cfg.webDomain,
|
||||
# http: {
|
||||
# paths: [
|
||||
# { path: "/", backend: app.svcWeb.name_port },
|
||||
# //{ path: "/static/", backend: app.svcStatic.name_port },
|
||||
# ],
|
||||
# },
|
||||
# },
|
||||
# ],
|
||||
# },
|
||||
#},
|
||||
|
||||
config: ns.Contain(kube.Secret("config")) {
|
||||
data_: {
|
||||
"postgres-pass": cfg.passwords.postgres,
|
||||
"django-secret-key": cfg.secrets.djangoSecretKey,
|
||||
|
||||
"smtp-password": cfg.smtp.password,
|
||||
|
||||
"mailman-api-password": cfg.mailmanCore.mailmanApiPass,
|
||||
"mailman-archiver-key": cfg.mailmanCore.mailmanArchiverKey,
|
||||
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
local mailman = import "mailman.libsonnet";
|
||||
local secrets = import "secrets/plain/prod.libsonnet";
|
||||
|
||||
mailman {
|
||||
cfg+: secrets {
|
||||
namespace: "mailman-hackerspace-prod",
|
||||
webDomain: "lists2.hackerspace.pl",
|
||||
|
||||
wg+: {
|
||||
address: "172.17.1.2/32",
|
||||
peerPubkey: "sKobxe3U6Gz72MWXEETTr8fSFIPSuX/WOGGFwd3oXy8=",
|
||||
endpoint: "boston-packets.hackerspace.pl:51820"
|
||||
},
|
||||
|
||||
//objectStorage+: {
|
||||
//bucket: "mailman-prod",
|
||||
//},
|
||||
|
||||
},
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
def main(argv):
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
|
||||
|
||||
os.environ['DJANGO_IS_MANAGEMENT_COMMAND'] = '1'
|
||||
from django.core.management import execute_from_command_line
|
||||
execute_from_command_line(argv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
|
@ -0,0 +1,38 @@
|
|||
import os
|
||||
import gunicorn.app.base
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
|
||||
class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
||||
|
||||
def __init__(self, app, options=None):
|
||||
self.options = options or {}
|
||||
self.application = app
|
||||
super().__init__()
|
||||
|
||||
def load_config(self):
|
||||
config = {key: value for key, value in self.options.items()
|
||||
if key in self.cfg.settings and value is not None}
|
||||
for key, value in config.items():
|
||||
self.cfg.set(key.lower(), value)
|
||||
|
||||
def load(self):
|
||||
return self.application
|
||||
|
||||
|
||||
def main():
|
||||
options = {
|
||||
'bind': os.environ.get('BIND_ADDR', '127.0.0.1:8080'),
|
||||
'workers': int(os.environ.get("GUNICORN_WORKERS", "4")),
|
||||
'capture_output': True,
|
||||
'disable_redirect_access_to_syslog': True,
|
||||
'accesslog': '-',
|
||||
'errorlog': '-',
|
||||
}
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
|
||||
application = get_wsgi_application()
|
||||
StandaloneApplication(application, options).run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -0,0 +1,102 @@
|
|||
import sys
|
||||
import os
|
||||
|
||||
from upstream_settings.base import *
|
||||
from upstream_settings.mailman import *
|
||||
|
||||
# we're in a container, stdout only
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'console': {
|
||||
'level': 'INFO',
|
||||
'class': 'logging.StreamHandler',
|
||||
'stream': sys.stdout,
|
||||
'formatter': 'verbose'
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'': {
|
||||
'handlers': ['console'],
|
||||
'level': 'INFO',
|
||||
'propagate': True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
SECRET_KEY = os.environ.get("SECRET_KEY", "hackme")
|
||||
# assert len(SECRET_KEY) > 16
|
||||
ROOT_URLCONF = "urls"
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
"localhost", # Archiving API from Mailman, keep it.
|
||||
os.environ.get('WEB_DOMAIN', "lists.hackerspace.pl"),
|
||||
]
|
||||
|
||||
ALLOWED_HOSTS = ["*"] # TODO deleteme
|
||||
|
||||
MAILMAN_REST_API_URL = 'http://localhost:8001'
|
||||
MAILMAN_REST_API_USER = 'restadmin'
|
||||
MAILMAN_REST_API_PASS = os.environ.get('MAILMAN_REST_API_PASS')
|
||||
MAILMAN_ARCHIVER_KEY = os.environ.get('MAILMAN_ARCHIVER_KEY')
|
||||
MAILMAN_ARCHIVER_FROM = ('127.0.0.1', '::1', '185.236.240.38', "2a0d:eb00:2137:2::10")
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
# Use 'sqlite3', 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
# DB name or path to database file if using sqlite3.
|
||||
'NAME': os.environ.get('DB_NAME', 'mailman-web'),
|
||||
# The following settings are not used with sqlite3:
|
||||
'USER': os.environ.get('DB_USER', 'mailman'),
|
||||
'PASSWORD': os.environ.get('DB_PASS'),
|
||||
# HOST: empty for localhost through domain sockets or '127.0.0.1' for
|
||||
# localhost through TCP.
|
||||
'HOST': os.environ.get('DB_HOST', '127.0.0.1'),
|
||||
# PORT: set to empty string for default.
|
||||
'PORT': os.environ.get('DB_PORT', ''),
|
||||
# OPTIONS: for mysql engine only, do not use with other engines.
|
||||
# 'OPTIONS': {'charset': 'utf8mb4'} # Enable utf8 4-byte encodings.
|
||||
}
|
||||
}
|
||||
|
||||
# TODO check this
|
||||
USE_X_FORWARDED_HOST = True # behind an Ingress
|
||||
|
||||
# And if your proxy does your SSL encoding for you, set SECURE_PROXY_SSL_HEADER
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#secure-proxy-ssl-header
|
||||
# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_SCHEME', 'https')
|
||||
|
||||
DEFAULT_FROM_EMAIL = 'postorius@hackerspace.pl'
|
||||
SERVER_EMAIL = 'bofh@hackerspace.pl'
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_HOST = os.environ.get('SMTP_HOST', '127.0.0.1')
|
||||
EMAIL_PORT = int(os.environ.get('SMTP_PORT', '465'))
|
||||
EMAIL_HOST_USER = os.environ.get('SMTP_USER', 'postorius')
|
||||
EMAIL_HOST_PASSWORD = os.environ.get('SMTP_PASSWORD')
|
||||
EMAIL_TIMEOUT=3
|
||||
EMAIL_USE_TLS=True
|
||||
|
||||
HAYSTACK_CONNECTIONS = {
|
||||
'default': {
|
||||
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
|
||||
'PATH': os.environ.get('FULLTEXT_INDEX_PATH', "fulltext_index"),
|
||||
# You can also use the Xapian engine, it's faster and more accurate,
|
||||
# but requires another library.
|
||||
# http://django-haystack.readthedocs.io/en/v2.4.1/installing_search_engines.html#xapian
|
||||
# Example configuration for Xapian:
|
||||
# 'ENGINE': 'xapian_backend.XapianEngine'
|
||||
},
|
||||
}
|
||||
|
||||
# Only display mailing-lists from the same virtual host as the webserver
|
||||
FILTER_VHOST = False
|
||||
POSTORIUS_TEMPLATE_BASE_URL = 'https://lists.hackerspace.pl'
|
|
@ -0,0 +1 @@
|
|||
Unmodified copy of default settings from mailman-web.
|
|
@ -0,0 +1,300 @@
|
|||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
from django.contrib.messages import constants as messages
|
||||
from pathlib import Path
|
||||
|
||||
#: The base directory for logs and database.
|
||||
BASE_DIR = Path('/opt/mailman/web')
|
||||
|
||||
#: Default list of admins who receive the emails from error logging.
|
||||
ADMINS = (
|
||||
('Mailman Suite Admin', 'root@localhost'),
|
||||
)
|
||||
|
||||
#: Hosts/domain names that are valid for this site; required if DEBUG is False.
|
||||
#: See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = [
|
||||
"localhost", # Archiving API from Mailman, keep it.
|
||||
# "lists.your-domain.org",
|
||||
# Add here all production URLs you may have.
|
||||
]
|
||||
|
||||
#: Enable Development Mode.
|
||||
DEBUG = False
|
||||
|
||||
|
||||
#: URL Configuration for Django
|
||||
ROOT_URLCONF = 'mailman_web.urls'
|
||||
|
||||
|
||||
#: Default list of django applications.
|
||||
#: Each social account provider is an application and by default no social auth
|
||||
#: providers are enabled. To enable a social auth provider, you can add them
|
||||
#: to list of INSTALLED_APPS. For example::
|
||||
#:
|
||||
#: DJANGO_SOCIAL_AUTH_PROVIDERS = [
|
||||
#: 'allauth.socialaccount.providers.openid',
|
||||
#: 'django_mailman3.lib.auth.fedora',
|
||||
#: 'allauth.socialaccount.providers.github',
|
||||
#: 'allauth.socialaccount.providers.gitlab',
|
||||
#: 'allauth.socialaccount.providers.google',
|
||||
#: 'allauth.socialaccount.providers.facebook',
|
||||
#: 'allauth.socialaccount.providers.twitter',
|
||||
#: 'allauth.socialaccount.providers.stackexchange',
|
||||
#: ]
|
||||
#: INSTALLED_APPS += DJANGO_SOCIAL_AUTH_PROVIDERS
|
||||
#:
|
||||
#: A full list of providers can be found at
|
||||
#: https://django-allauth.readthedocs.io/en/latest/providers.html
|
||||
#: Please also note that extra configuration is required after
|
||||
#: a provider is enabled. Django-allauth's documentation mentioned
|
||||
#: above provides more details about how to configure one.
|
||||
INSTALLED_APPS = [
|
||||
'hyperkitty',
|
||||
'postorius',
|
||||
'django_mailman3',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'rest_framework',
|
||||
'django_gravatar',
|
||||
'compressor',
|
||||
'haystack',
|
||||
'django_extensions',
|
||||
'django_q',
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'allauth.socialaccount',
|
||||
]
|
||||
|
||||
|
||||
#: Default Django Middlewares.
|
||||
MIDDLEWARE = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django_mailman3.middleware.TimezoneMiddleware',
|
||||
'postorius.middleware.PostoriusMiddleware',
|
||||
)
|
||||
|
||||
#: Default Template finders.
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.i18n',
|
||||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.static',
|
||||
'django.template.context_processors.tz',
|
||||
'django.template.context_processors.csrf',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'django_mailman3.context_processors.common',
|
||||
'hyperkitty.context_processors.common',
|
||||
'postorius.context_processors.postorius',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
#: Wsgi application import path. This will be used by the WSGI server which
|
||||
#: will be used to deploy this application.
|
||||
WSGI_APPLICATION = 'mailman_web.wsgi.application'
|
||||
|
||||
#: Default Database to be used.
|
||||
#: Example for PostgreSQL (**recommanded for production**)::
|
||||
#:
|
||||
#: 'default': {
|
||||
#: 'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
#: 'NAME': 'database_name',
|
||||
#: 'USER': 'database_user',
|
||||
#: 'PASSWORD': 'database_password',
|
||||
#: 'HOST': 'localhost',
|
||||
#: }
|
||||
#:
|
||||
#: For MySQL/MariaDB also add the following to the the configuration::
|
||||
#:
|
||||
#: 'OPTIONS': {'charset': 'utf8mb4'} # Enable utf8 4-byte encodings.
|
||||
#:
|
||||
#: Check out
|
||||
#: `Django documentation
|
||||
#: <https://docs.djangoproject.com/en/3.0/ref/settings/#databases>`_ for
|
||||
#: more details.
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'mailman-web.db'),
|
||||
'HOST': '',
|
||||
'PORT': '',
|
||||
}
|
||||
}
|
||||
|
||||
# Maintain type of autogenerated keys going forward
|
||||
# https://docs.djangoproject.com/en/3.2/releases/3.2/#customizing-type-of-auto-created-primary-keys
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
||||
|
||||
|
||||
#: Default password validators.
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME':
|
||||
'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', # noqa: E501
|
||||
},
|
||||
{
|
||||
'NAME':
|
||||
'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME':
|
||||
'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME':
|
||||
'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
#: Default Language code.
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
#: Default timezone.
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
#: Enable internationalization.
|
||||
USE_I18N = True
|
||||
|
||||
#: Enable localization.
|
||||
USE_L10N = True
|
||||
|
||||
#: Use the timezone information.
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
#: Default path where static files will be placed.
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
|
||||
|
||||
#: URL prefix for static files.
|
||||
#: Example: "http://example.com/static/", "http://static.example.com/"
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
#: Additional locations of static files
|
||||
STATICFILES_DIRS = (
|
||||
# Put strings here, like "/home/html/static" or "C:/www/django/static".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
# BASE_DIR + '/static/',
|
||||
)
|
||||
|
||||
#: List of finder classes that know how to find static files in
|
||||
#: various locations.
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
|
||||
#: Default Django URL to redirect to for Login.
|
||||
LOGIN_URL = 'account_login'
|
||||
#: Default Django URL to redirect to after a successful login.
|
||||
LOGIN_REDIRECT_URL = 'list_index'
|
||||
#: Default Django URL to Logout the user.
|
||||
LOGOUT_URL = 'account_logout'
|
||||
|
||||
#: If you enable email reporting for error messages, this is where those emails
|
||||
#: will appear to be coming from. Make sure you set a valid domain name,
|
||||
#: otherwise the emails may get rejected.
|
||||
#: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SERVER_EMAIL
|
||||
SERVER_EMAIL = 'root@localhost.local'
|
||||
|
||||
#: The default implementation to send out emails. This can be customized to
|
||||
#: something else for testing purposes.
|
||||
#: https://docs.djangoproject.com/en/dev/topics/email/#email-backends
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
|
||||
MESSAGE_TAGS = {
|
||||
messages.ERROR: 'danger'
|
||||
}
|
||||
|
||||
|
||||
#: Default Logging configuration.
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
},
|
||||
'file': {
|
||||
'level': 'INFO',
|
||||
'class': 'logging.handlers.WatchedFileHandler',
|
||||
'filename': os.path.join(BASE_DIR, 'logs', 'mailmanweb.log'),
|
||||
'formatter': 'verbose',
|
||||
},
|
||||
'console': {
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simple',
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins', 'file'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
'django': {
|
||||
'handlers': ['file'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True,
|
||||
},
|
||||
'hyperkitty': {
|
||||
'handlers': ['file'],
|
||||
'level': 'DEBUG',
|
||||
'propagate': True,
|
||||
},
|
||||
'postorius': {
|
||||
'handlers': ['console', 'file'],
|
||||
'level': 'INFO',
|
||||
},
|
||||
'q': {
|
||||
'level': 'WARNING',
|
||||
'propagate': False,
|
||||
'handlers': ['console', 'file'],
|
||||
},
|
||||
},
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '%(levelname)s %(asctime)s %(process)d %(name)s %(message)s' # noqa: E501
|
||||
},
|
||||
'simple': {
|
||||
'format': '%(levelname)s %(message)s'
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
#: Current Django Site being served. This is used to customize the web host
|
||||
#: being used to serve the current website. For more details about Django
|
||||
#: site, see: https://docs.djangoproject.com/en/dev/ref/contrib/sites/
|
||||
SITE_ID = 1
|
|
@ -0,0 +1,124 @@
|
|||
#: Mailman Core default API Path
|
||||
MAILMAN_REST_API_URL = 'http://localhost:8001'
|
||||
#: Mailman Core API user
|
||||
MAILMAN_REST_API_USER = 'restadmin'
|
||||
#: Mailman Core API user's password.
|
||||
MAILMAN_REST_API_PASS = 'restpass'
|
||||
#: Mailman Core Shared archiving key. This value is set in the :
|
||||
#: mailman-hyperkitty's configuration file.
|
||||
MAILMAN_ARCHIVER_KEY = 'SecretArchiverAPIKey'
|
||||
#: Host for Mailman Core, from where Hyperkitty will accept connections
|
||||
#: for archiving.
|
||||
MAILMAN_ARCHIVER_FROM = ('127.0.0.1', '::1')
|
||||
|
||||
#: Base URL where Django/Mailman-web would be listening for requests. Used by
|
||||
#: Mailman Core for fetching templates.
|
||||
POSTORIUS_TEMPLATE_BASE_URL = 'http://localhost:8000'
|
||||
|
||||
#: Use gravatar in HyperKitty and Postorius.
|
||||
#: If disabled django_gravatar can be removed from INSTALLED_APPS:
|
||||
#: INSTALLED_APPS.remove('django_gravatar')
|
||||
HYPERKITTY_ENABLE_GRAVATAR = True
|
||||
|
||||
#: Filter visible Mailing Lists based on the current host being used to serve.
|
||||
FILTER_VHOST = False
|
||||
|
||||
#: Sender in Emails sent out by Postorius.
|
||||
DEFAULT_FROM_EMAIL = 'postorius@localhost'
|
||||
|
||||
|
||||
#: Django Allauth
|
||||
ACCOUNT_AUTHENTICATION_METHOD = "username_email"
|
||||
ACCOUNT_EMAIL_REQUIRED = True
|
||||
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
|
||||
ACCOUNT_UNIQUE_EMAIL = True
|
||||
|
||||
#: Protocol for URLs generated for authentication, like email
|
||||
#: confirmation.
|
||||
ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https"
|
||||
|
||||
|
||||
#: Extra configuration for Social auth. For these configuration to be used.
|
||||
#: each of the social account providers must be first added in INSTALLED_APPS.
|
||||
#: See :py:data:`mailman_web.settings.base.INSTALLED_APPS` for more
|
||||
#: configuration.
|
||||
SOCIALACCOUNT_PROVIDERS = {
|
||||
'openid': {
|
||||
'SERVERS': [
|
||||
dict(id='yahoo',
|
||||
name='Yahoo',
|
||||
openid_url='http://me.yahoo.com'),
|
||||
],
|
||||
},
|
||||
'google': {
|
||||
'SCOPE': ['profile', 'email'],
|
||||
'AUTH_PARAMS': {'access_type': 'online'},
|
||||
},
|
||||
'facebook': {
|
||||
'METHOD': 'oauth2',
|
||||
'SCOPE': ['email'],
|
||||
'FIELDS': [
|
||||
'email',
|
||||
'name',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'locale',
|
||||
'timezone',
|
||||
],
|
||||
'VERSION': 'v2.4',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
#: django-compressor
|
||||
#: https://pypi.python.org/pypi/django_compressor
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/x-scss', 'sassc -t compressed {infile} {outfile}'),
|
||||
('text/x-sass', 'sassc -t compressed {infile} {outfile}'),
|
||||
)
|
||||
|
||||
|
||||
# Social auth
|
||||
#
|
||||
#: Authentication backends for Django to be used.
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
'allauth.account.auth_backends.AuthenticationBackend',
|
||||
)
|
||||
|
||||
#
|
||||
# Full-text search engine
|
||||
#
|
||||
#: Django-Haystack connection parameters.
|
||||
HAYSTACK_CONNECTIONS = {
|
||||
'default': {
|
||||
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
|
||||
'PATH': "fulltext_index",
|
||||
# You can also use the Xapian engine, it's faster and more accurate,
|
||||
# but requires another library.
|
||||
# http://django-haystack.readthedocs.io/en/v2.4.1/installing_search_engines.html#xapian
|
||||
# Example configuration for Xapian:
|
||||
# 'ENGINE': 'xapian_backend.XapianEngine'
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# Asynchronous tasks
|
||||
#
|
||||
#: Django Q connection parameters.
|
||||
Q_CLUSTER = {
|
||||
'retry': 360,
|
||||
'timeout': 300,
|
||||
'save_limit': 100,
|
||||
'orm': 'default',
|
||||
}
|
||||
|
||||
#: On a production setup, setting COMPRESS_OFFLINE to True will bring a
|
||||
#: significant performance improvement, as CSS files will not need to be
|
||||
#: recompiled on each requests. It means running an additional "compress"
|
||||
#: management command after each code upgrade.
|
||||
#: http://django-compressor.readthedocs.io/en/latest/usage/#offline-compression
|
||||
COMPRESS_OFFLINE = True
|
||||
|
||||
# Needed for debug mode
|
||||
# INTERNAL_IPS = ('127.0.0.1',)
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 1998-2016 by the Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of Postorius.
|
||||
#
|
||||
# Postorius is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Postorius is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Postorius. If not, see <http://www.gnu.org/licenses/>.
|
||||