├── .gitignore ├── .gitattributes ├── operator ├── .gitignore ├── defaults │ ├── paper.yml │ ├── velocity.toml │ ├── prometheus.yaml │ └── server.properties ├── src │ ├── helpers │ │ ├── mod.rs │ │ ├── telemetry.rs │ │ ├── state.rs │ │ ├── jarapi.rs │ │ ├── metrics.rs │ │ └── manager.rs │ ├── crdgen.rs │ ├── lib.rs │ ├── main.rs │ ├── objects │ │ ├── minecraft_set.rs │ │ ├── minecraft_proxy.rs │ │ └── mod.rs │ └── runner.rs ├── chart │ ├── templates │ │ ├── operator-secret.yaml │ │ ├── operator-service.yaml │ │ ├── operator-acl.yaml │ │ └── operator-statefulset.yaml │ ├── .helmignore │ ├── values.yaml │ └── Chart.yaml ├── rustfmt.toml ├── operator.Dockerfile ├── runner.Dockerfile ├── Cargo.toml └── Cargo.lock ├── plugin ├── settings.gradle.kts ├── paper │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── plugin.yml │ │ │ └── kotlin │ │ │ └── Plugin.kt │ └── build.gradle.kts ├── build.gradle.kts ├── common │ └── build.gradle.kts ├── velocity │ ├── src │ │ └── main │ │ │ └── kotlin │ │ │ └── dev │ │ │ └── njha │ │ │ └── mycelium │ │ │ └── plugin │ │ │ └── velocity │ │ │ ├── metrics │ │ │ ├── MetricsCollection.kt │ │ │ └── MetricsCollector.kt │ │ │ ├── models │ │ │ └── Server.kt │ │ │ └── Plugin.kt │ ├── gradle.properties │ ├── build.gradle.kts │ └── .gitignore ├── gradle.properties ├── gradlew.bat ├── gradlew └── .gitignore ├── LICENSE ├── SECURITY.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | testing/ 2 | .idea/ 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | Cargo.lock linguist-generated 2 | -------------------------------------------------------------------------------- /operator/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.idea 3 | /testing 4 | -------------------------------------------------------------------------------- /operator/defaults/paper.yml: -------------------------------------------------------------------------------- 1 | config-version: 20 2 | settings: 3 | velocity-support: 4 | enabled: true -------------------------------------------------------------------------------- /plugin/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "mycelium-plugin" 2 | include("velocity") 3 | include("common") 4 | include("paper") 5 | -------------------------------------------------------------------------------- /operator/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod jarapi; 2 | pub mod manager; 3 | pub mod metrics; 4 | pub mod state; 5 | /// logging and tracing 6 | pub mod telemetry; 7 | -------------------------------------------------------------------------------- /plugin/paper/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | main: Plugin 2 | name: Mycelium 3 | version: 0.4.0 4 | api-version: "1.18" 5 | author: Nikhil Jha 6 | description: build Minecraft networks at planet scale -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 Nikhil Jha 2 | All Rights Reserved 3 | 4 | Commercial use licenses and support contracts are available for sale. Please contact me for more information. 5 | -------------------------------------------------------------------------------- /operator/defaults/velocity.toml: -------------------------------------------------------------------------------- 1 | config-version = "1.0" 2 | bind = "0.0.0.0:25577" 3 | player-info-forwarding-mode = "modern" 4 | forwarding-secret = "secret_here" 5 | 6 | [servers] 7 | try = [] 8 | 9 | [forced-hosts] -------------------------------------------------------------------------------- /operator/chart/templates/operator-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: mycelium-operator 5 | namespace: {{ .Release.Namespace }} 6 | type: Opaque 7 | stringData: 8 | forwarding_token: "{{- randAlphaNum 16 | nospace -}}" 9 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | < 1.0 | :x: | 8 | 9 | ## Reporting a Vulnerability 10 | 11 | email with details 12 | -------------------------------------------------------------------------------- /operator/src/crdgen.rs: -------------------------------------------------------------------------------- 1 | use kube::CustomResourceExt; 2 | use mycelium::{MinecraftProxy, MinecraftSet}; 3 | 4 | fn main() { 5 | println!("{}", serde_yaml::to_string(&MinecraftSet::crd()).unwrap()); 6 | println!("{}", serde_yaml::to_string(&MinecraftProxy::crd()).unwrap()); 7 | } 8 | -------------------------------------------------------------------------------- /plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | val myceliumVersion by extra { "0.4.0" } 2 | 3 | plugins { 4 | id("com.github.johnrengelman.shadow") version "6.1.0" apply false 5 | } 6 | 7 | tasks.register("alljars") { 8 | dependsOn(":paper:shadowJar") 9 | dependsOn(":velocity:shadowJar") 10 | } 11 | -------------------------------------------------------------------------------- /plugin/common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") version "1.6.10" 3 | } 4 | 5 | group = "dev.njha.mycelium" 6 | val myceliumVersion: String by rootProject.extra 7 | version = myceliumVersion 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | implementation(kotlin("stdlib")) 15 | } -------------------------------------------------------------------------------- /operator/chart/templates/operator-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: mycelium-operator 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | app: mycelium-operator 8 | spec: 9 | ports: 10 | - port: 8080 11 | targetPort: 8080 12 | name: api 13 | selector: 14 | app: mycelium-operator -------------------------------------------------------------------------------- /operator/rustfmt.toml: -------------------------------------------------------------------------------- 1 | condense_wildcard_suffixes = true 2 | format_strings = true 3 | imports_granularity = "Crate" 4 | newline_style = "Unix" 5 | normalize_comments = true 6 | normalize_doc_attributes = true 7 | overflow_delimited_expr = true 8 | reorder_impl_items = true 9 | group_imports = "StdExternalCrate" 10 | use_try_shorthand = true 11 | wrap_comments = true -------------------------------------------------------------------------------- /operator/src/helpers/telemetry.rs: -------------------------------------------------------------------------------- 1 | use crate::{Error, Result}; 2 | 3 | pub fn get_trace_id() -> String { 4 | use opentelemetry::trace::TraceContextExt; 5 | use tracing_opentelemetry::OpenTelemetrySpanExt; 6 | 7 | tracing::Span::current() 8 | .context() 9 | .span() 10 | .span_context() 11 | .trace_id() 12 | .to_hex() 13 | } 14 | -------------------------------------------------------------------------------- /operator/operator.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM clux/muslrust:1.57.0 as builder 2 | WORKDIR ./volume 3 | COPY ./Cargo.toml ./Cargo.toml 4 | COPY ./Cargo.lock ./Cargo.lock 5 | COPY ./src ./src 6 | RUN cargo build --release --bin mycelium-operator 7 | 8 | FROM gcr.io/distroless/static:nonroot 9 | COPY --from=builder /volume/volume/target/x86_64-unknown-linux-musl/release/mycelium-operator /app/ 10 | EXPOSE 8080 11 | CMD ["/app/mycelium-operator"] 12 | -------------------------------------------------------------------------------- /operator/src/helpers/state.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Utc}; 2 | use serde::Serialize; 3 | 4 | /// in-memory reconciler state exposed on /state 5 | #[derive(Clone, Serialize)] 6 | pub struct State { 7 | #[serde(deserialize_with = "from_ts")] 8 | pub last_event: DateTime, 9 | } 10 | 11 | impl State { 12 | pub(crate) fn new() -> Self { 13 | State { 14 | last_event: Utc::now(), 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /operator/chart/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /plugin/velocity/src/main/kotlin/dev/njha/mycelium/plugin/velocity/metrics/MetricsCollection.kt: -------------------------------------------------------------------------------- 1 | package dev.njha.mycelium.plugin.velocity.metrics 2 | 3 | import dev.cubxity.plugins.metrics.api.metric.collector.Collector 4 | import dev.cubxity.plugins.metrics.api.metric.collector.CollectorCollection 5 | 6 | 7 | class MetricsCollection(collector: MetricsCollector) : CollectorCollection { 8 | override val collectors: List = listOf(collector) 9 | } 10 | -------------------------------------------------------------------------------- /plugin/velocity/src/main/kotlin/dev/njha/mycelium/plugin/velocity/metrics/MetricsCollector.kt: -------------------------------------------------------------------------------- 1 | package dev.njha.mycelium.plugin.velocity.metrics 2 | 3 | import dev.cubxity.plugins.metrics.api.metric.collector.Collector 4 | import dev.cubxity.plugins.metrics.api.metric.data.GaugeMetric 5 | import dev.cubxity.plugins.metrics.api.metric.data.Metric 6 | 7 | 8 | class MetricsCollector() : Collector { 9 | var churn = 0 10 | 11 | override fun collect(): List { 12 | val metric = GaugeMetric("mycelium_proxy_churn", hashMapOf(), churn) 13 | return listOf(metric) 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /operator/defaults/prometheus.yaml: -------------------------------------------------------------------------------- 1 | mode: "HTTP" # "HTTP" or "PUSHGATEWAY" 2 | 3 | # Applies to "HTTP" mode. 4 | http: 5 | host: "0.0.0.0" 6 | port: 9970 # The default in 0.4.x will be 9970. 7 | authentication: 8 | scheme: "NONE" # "NONE" or "BASIC" 9 | username: "username" 10 | password: "password" 11 | 12 | # Applies to "PUSHGATEWAY" mode. 13 | # Note that this is NOT compatible with remote_write. 14 | pushGateway: 15 | job: "unifiedmetrics" 16 | url: "http://pushgateway:9091" 17 | authentication: 18 | scheme: "BASIC" # "NONE" or "BASIC" 19 | username: "username" 20 | password: "password" 21 | interval: 10 -------------------------------------------------------------------------------- /operator/runner.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.hub.docker.com/library/rust:1.57 as builder 2 | 3 | WORKDIR ./mycelium-runner 4 | COPY ./Cargo.toml ./Cargo.toml 5 | COPY ./Cargo.lock ./Cargo.lock 6 | COPY ./src ./src 7 | COPY ./defaults ./defaults 8 | RUN cargo build --release --bin mycelium-runner 9 | 10 | 11 | FROM openjdk:17-slim-bullseye 12 | 13 | RUN apt-get update && apt-get install -y curl 14 | RUN apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/ 15 | 16 | ENV MYCELIUM_CONFIG_PATH=/config 17 | ENV MYCELIUM_DATA_PATH=/data 18 | RUN mkdir -p /config && mkdir -p /data 19 | 20 | COPY --from=builder /mycelium-runner/target/release/mycelium-runner /mycelium-runner 21 | CMD ["/mycelium-runner"] 22 | -------------------------------------------------------------------------------- /plugin/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=--illegal-access=permit -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options="--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" 2 | kapt.use.worker.api=true 3 | -------------------------------------------------------------------------------- /plugin/velocity/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | org.gradle.jvmargs=--illegal-access=permit -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options="--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" 3 | kapt.use.worker.api=false 4 | -------------------------------------------------------------------------------- /plugin/velocity/src/main/kotlin/dev/njha/mycelium/plugin/velocity/models/Server.kt: -------------------------------------------------------------------------------- 1 | package dev.njha.mycelium.plugin.velocity.models 2 | 3 | import kotlinx.serialization.* 4 | import javax.annotation.Nullable 5 | 6 | @Serializable 7 | data class Server(val name: String, val address: String, @Nullable val host: String?, @Nullable val priority: Int?) : Comparable { 8 | override fun compareTo(other: Server): Int { 9 | if (priority == null && other.priority == null) { 10 | return 0 11 | } else if (priority == null) { 12 | return -1 13 | } else if (other.priority == null) { 14 | return 1 15 | } else if (priority < other.priority) { 16 | return -1 17 | } else if (other.priority > priority) { 18 | return 1 19 | } 20 | return 0 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /operator/chart/values.yaml: -------------------------------------------------------------------------------- 1 | images: 2 | pullPolicy: IfNotPresent 3 | operator: "harbor.ocf.berkeley.edu/mycelium/operator:{{ .Chart.AppVersion }}" 4 | runner: "harbor.ocf.berkeley.edu/mycelium/runner:{{ .Chart.AppVersion }}" 5 | 6 | plugins: 7 | mycelium: 8 | velocity: "https://www.ocf.berkeley.edu/~njha/artifacts/mycelium-velocity-{{ .Chart.AppVersion }}.jar" 9 | paper: "https://www.ocf.berkeley.edu/~njha/artifacts/mycelium-paper-{{ .Chart.AppVersion }}.jar" 10 | metrics: 11 | velocity: "https://github.com/Cubxity/UnifiedMetrics/releases/download/v0.3.4/unifiedmetrics-platform-velocity-0.3.4.jar" 12 | paper: "https://github.com/Cubxity/UnifiedMetrics/releases/download/v0.3.4/unifiedmetrics-platform-bukkit-0.3.4.jar" 13 | 14 | # resources for the operator ONLY - server and proxy resources 15 | # are managed in the MinecraftSet and MinecraftProxy CRDs 16 | resources: 17 | limits: 18 | cpu: 200m 19 | memory: 256Mi 20 | requests: 21 | cpu: 50m 22 | memory: 100Mi 23 | -------------------------------------------------------------------------------- /operator/chart/templates/operator-acl.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: mycelium-operator 6 | namespace: {{ .Release.Namespace }} 7 | automountServiceAccountToken: true 8 | 9 | --- 10 | kind: ClusterRole 11 | apiVersion: rbac.authorization.k8s.io/v1 12 | metadata: 13 | name: mycelium-operator 14 | rules: 15 | - apiGroups: ["mycelium.njha.dev"] 16 | resources: ["*"] 17 | verbs: ["*"] 18 | # TODO: Can we restrict this to only children of mycelium CRDs? 19 | - apiGroups: ["*"] 20 | resources: ["statefulsets", "services", "events", "secrets", "poddisruptionbudgets"] 21 | verbs: ["*"] 22 | 23 | --- 24 | kind: ClusterRoleBinding 25 | apiVersion: rbac.authorization.k8s.io/v1 26 | metadata: 27 | name: mycelium-operator 28 | subjects: 29 | - kind: ServiceAccount 30 | namespace: {{ .Release.Namespace }} 31 | name: mycelium-operator 32 | roleRef: 33 | kind: ClusterRole 34 | name: mycelium-operator 35 | apiGroup: rbac.authorization.k8s.io -------------------------------------------------------------------------------- /operator/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(unused_imports)] 3 | 4 | use std::fmt::{Display, Formatter}; 5 | pub use objects::{minecraft_proxy::MinecraftProxy, minecraft_set::MinecraftSet}; 6 | use thiserror::Error; 7 | use thiserror::private::DisplayAsDisplay; 8 | 9 | #[derive(Error, Debug)] 10 | pub enum Error { 11 | #[error("Kube Api Error: {0}")] 12 | KubeError(#[from] kube::Error), 13 | 14 | #[error("SerializationError: {0}")] 15 | SerializationError(#[source] serde_json::Error), 16 | 17 | #[error("ReqwestError: {0}")] 18 | ReqwestError(#[from] reqwest::Error), 19 | 20 | #[error("VarError: {0}")] 21 | VarError(#[from] std::env::VarError), 22 | 23 | #[error("MyceliumError: {0}")] 24 | MyceliumError(String), 25 | 26 | #[error(transparent)] 27 | Other(#[from] anyhow::Error), 28 | } 29 | 30 | impl actix_web::error::ResponseError for Error {} 31 | 32 | pub type Result = std::result::Result; 33 | 34 | pub mod helpers; 35 | /// generated types 36 | pub mod objects; 37 | -------------------------------------------------------------------------------- /plugin/paper/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") version "1.6.10" 3 | kotlin("kapt") version "1.6.10" 4 | id("com.github.johnrengelman.shadow") 5 | } 6 | 7 | group = "dev.njha.mycelium" 8 | val myceliumVersion: String by rootProject.extra 9 | version = myceliumVersion 10 | 11 | repositories { 12 | mavenCentral() 13 | maven("https://papermc.io/repo/repository/maven-public/") 14 | } 15 | 16 | dependencies { 17 | implementation(kotlin("stdlib")) 18 | implementation(project(":common")) 19 | 20 | implementation("io.ktor:ktor-server-core:1.6.7") 21 | implementation("io.ktor:ktor-server-netty:1.6.7") 22 | implementation("io.ktor:ktor-client-core:1.6.7") 23 | implementation("io.ktor:ktor-client-java:1.6.7") 24 | implementation("io.ktor:ktor-gson:1.6.7") 25 | 26 | compileOnly("io.papermc.paper:paper-api:1.18.1-R0.1-SNAPSHOT") 27 | compileOnly("dev.cubxity.plugins:unifiedmetrics-api:0.3.4") 28 | kapt("io.papermc.paper:paper-api:1.18.1-R0.1-SNAPSHOT") 29 | } 30 | 31 | tasks { 32 | val shadowJar by getting(com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class) { 33 | archiveFileName.set("mycelium-${project.name}-${project.version}.jar") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /operator/chart/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: mycelium 3 | description: Minecraft @ Scale 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.4.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "0.4.0" 25 | -------------------------------------------------------------------------------- /plugin/paper/src/main/kotlin/Plugin.kt: -------------------------------------------------------------------------------- 1 | import com.typesafe.config.ConfigFactory 2 | import io.ktor.application.* 3 | import io.ktor.config.* 4 | import io.ktor.features.* 5 | import io.ktor.gson.* 6 | import io.ktor.http.* 7 | import io.ktor.response.* 8 | import io.ktor.routing.* 9 | import io.ktor.server.engine.* 10 | import io.ktor.server.netty.* 11 | import org.bukkit.plugin.java.JavaPlugin 12 | import org.slf4j.LoggerFactory 13 | 14 | class Plugin : JavaPlugin() { 15 | override fun onEnable() { 16 | val ews = embeddedServer(Netty, environment = applicationEngineEnvironment { 17 | log = LoggerFactory.getLogger("mycelium") 18 | config = HoconApplicationConfig(ConfigFactory.load()) 19 | 20 | module { 21 | install(ContentNegotiation) { 22 | gson() 23 | } 24 | routing { 25 | get("/") { 26 | call.respondText("ok", ContentType.Text.Plain) 27 | } 28 | } 29 | } 30 | 31 | connector { 32 | port = 9273 33 | host = "0.0.0.0" 34 | } 35 | }) 36 | ews.start(wait = false) 37 | } 38 | } -------------------------------------------------------------------------------- /operator/defaults/server.properties: -------------------------------------------------------------------------------- 1 | #Minecraft server properties 2 | #Sat Dec 25 00:18:43 UTC 2021 3 | #Generated by Mycelium 4 | enable-jmx-monitoring=false 5 | rcon.port=25575 6 | gamemode=survival 7 | enable-command-block=false 8 | enable-query=false 9 | level-name=world 10 | motd=A Minecraft Server 11 | query.port=25565 12 | pvp=true 13 | difficulty=easy 14 | network-compression-threshold=256 15 | require-resource-pack=false 16 | max-tick-time=60000 17 | use-native-transport=true 18 | max-players=20 19 | online-mode=false 20 | enable-status=true 21 | allow-flight=false 22 | broadcast-rcon-to-ops=true 23 | view-distance=10 24 | server-ip= 25 | resource-pack-prompt= 26 | allow-nether=true 27 | server-port=25565 28 | enable-rcon=false 29 | sync-chunk-writes=true 30 | op-permission-level=4 31 | prevent-proxy-connections=false 32 | hide-online-players=false 33 | resource-pack= 34 | entity-broadcast-range-percentage=100 35 | simulation-distance=10 36 | rcon.password= 37 | player-idle-timeout=0 38 | debug=false 39 | force-gamemode=false 40 | rate-limit=0 41 | hardcore=false 42 | white-list=false 43 | broadcast-console-to-ops=true 44 | spawn-npcs=true 45 | spawn-animals=true 46 | function-permission-level=2 47 | text-filtering-config= 48 | spawn-monsters=true 49 | enforce-whitelist=false 50 | resource-pack-sha1= 51 | spawn-protection=16 52 | max-world-size=29999984 53 | -------------------------------------------------------------------------------- /operator/src/helpers/jarapi.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::format; 2 | 3 | use serde::{Deserialize, Serialize}; 4 | 5 | use crate::Error; 6 | 7 | #[derive(Serialize, Deserialize, Debug)] 8 | struct Versions { 9 | project_id: String, 10 | project_name: String, 11 | version_groups: Vec, 12 | versions: Vec, 13 | } 14 | 15 | #[derive(Serialize, Deserialize, Debug)] 16 | struct Builds { 17 | project_id: String, 18 | project_name: String, 19 | version: String, 20 | builds: Vec, 21 | } 22 | 23 | pub async fn get_versions(kind: &str) -> Result, Error> { 24 | let url = format!("https://papermc.io/api/v2/projects/{kind}", kind = kind); 25 | // .header("User-Agent", format!("mycelium/{}", env!("CARGO_PKG_VERSION"))) 26 | let resp = reqwest::get(url).await?.json::().await?; 27 | Ok(resp.versions) 28 | } 29 | 30 | pub async fn get_builds(kind: &str, version: &str) -> Result, Error> { 31 | let url = format!( 32 | "https://papermc.io/api/v2/projects/{kind}/versions/{version}", 33 | kind = kind, 34 | version = version 35 | ); 36 | // .header("User-Agent", format!("mycelium/{}", env!("CARGO_PKG_VERSION"))) 37 | let resp = reqwest::get(url).await?.json::().await?; 38 | Ok(resp.builds) 39 | } 40 | 41 | pub fn get_download_url(kind: &str, version: &str, build: &str) -> String { 42 | format!( 43 | "https://papermc.io/api/v2/projects/{kind}/versions/{version}/builds/{build}/downloads/{kind}-{version}-{build}.jar", 44 | version = version, build = build, kind = kind 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /operator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mycelium" 3 | version = "0.4.0" 4 | authors = ["Nikhil Jha "] 5 | edition = "2021" 6 | default-run = "mycelium-operator" 7 | 8 | [[bin]] 9 | name = "mycelium-operator" 10 | path = "src/main.rs" 11 | 12 | [[bin]] 13 | name = "mycelium-crdgen" 14 | path = "src/crdgen.rs" 15 | 16 | [[bin]] 17 | name = "mycelium-runner" 18 | path = "src/runner.rs" 19 | 20 | [lib] 21 | name = "mycelium" 22 | path = "src/lib.rs" 23 | 24 | [features] 25 | default = [] 26 | telemetry = [] 27 | 28 | [dependencies] 29 | actix-rt = "2.5.0" 30 | actix-web = "4.0.0-beta.15" 31 | futures = "0.3.15" 32 | tokio = { version = "1.6.0", features = ["macros"] } 33 | kube = { version = "0.65.0", features = ["derive"] } 34 | kube-runtime = "0.65.0" 35 | k8s-openapi = { version = "0.13.1", features = ["v1_22", "schemars"], default-features = false } 36 | serde = { version = "1.0.126", features = ["derive"] } 37 | serde_json = "1.0.64" 38 | chrono = { version = "0.4.19", features = ["serde"] } 39 | thiserror = "1.0.24" 40 | schemars = { version = "0.8.8", features = ["chrono"] } 41 | serde_yaml = "0.8.17" 42 | maplit = "1.0.2" 43 | tracing = "0.1.26" 44 | tracing-subscriber = { version = "0.2.18", features = ["json"] } 45 | tracing-opentelemetry = "0.12.0" 46 | opentelemetry = { version = "0.13.0", features = ["trace", "rt-tokio"] } 47 | opentelemetry-otlp = { version = "0.6.0", features = ["tokio"] } 48 | prometheus = "0.12.0" 49 | anyhow = "1.0.42" 50 | reqwest = { version = "0.11.8", features = ["json"] } 51 | toml_edit = "0.12.0" 52 | yaml-rust = "0.4.5" 53 | linked-hash-map = "0.5.4" 54 | signal-hook = "0.3.13" 55 | nix = "0.23.1" 56 | sha2 = "0.10.0" 57 | base64 = "0.13.0" 58 | -------------------------------------------------------------------------------- /operator/src/helpers/metrics.rs: -------------------------------------------------------------------------------- 1 | use prometheus::{register_histogram_vec, register_int_counter, HistogramVec, IntCounter}; 2 | 3 | /// prometheus metrics exposed on /metrics 4 | #[derive(Clone)] 5 | pub struct Metrics { 6 | pub set_handled_events: IntCounter, 7 | pub proxy_handled_events: IntCounter, 8 | pub set_reconcile_duration: HistogramVec, 9 | pub proxy_reconcile_duration: HistogramVec, 10 | } 11 | 12 | impl Metrics { 13 | pub(crate) fn new() -> Self { 14 | let set_reconcile_histogram = register_histogram_vec!( 15 | "mcset_controller_reconcile_duration_seconds", 16 | "The duration of mcset reconcile to complete in seconds", 17 | &[], 18 | vec![0.01, 0.1, 0.25, 0.5, 1., 5., 15., 60.] 19 | ) 20 | .unwrap(); 21 | 22 | let proxy_reconcile_histogram = register_histogram_vec!( 23 | "mcproxy_controller_reconcile_duration_seconds", 24 | "The duration of mcproxy reconcile to complete in seconds", 25 | &[], 26 | vec![0.01, 0.1, 0.25, 0.5, 1., 5., 15., 60.] 27 | ) 28 | .unwrap(); 29 | 30 | Metrics { 31 | set_handled_events: register_int_counter!( 32 | "mcset_controller_handled_events", 33 | "mcset handled events" 34 | ) 35 | .unwrap(), 36 | proxy_handled_events: register_int_counter!( 37 | "proxy_controller_handled_events", 38 | "proxy handled events" 39 | ) 40 | .unwrap(), 41 | set_reconcile_duration: set_reconcile_histogram, 42 | proxy_reconcile_duration: proxy_reconcile_histogram, 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /plugin/velocity/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") version "1.6.10" 5 | kotlin("plugin.serialization") version "1.6.10" 6 | kotlin("kapt") version "1.6.10" 7 | id("com.github.johnrengelman.shadow") 8 | } 9 | 10 | group = "dev.njha.mycelium" 11 | val myceliumVersion: String by rootProject.extra 12 | version = myceliumVersion 13 | 14 | repositories { 15 | mavenCentral() 16 | jcenter() 17 | maven(url= "https://nexus.velocitypowered.com/repository/maven-public/") 18 | } 19 | 20 | dependencies { 21 | testImplementation(kotlin("test-junit5")) 22 | testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") 23 | testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2") 24 | 25 | implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") 26 | implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") 27 | implementation("io.ktor:ktor-server-core:1.6.7") 28 | implementation("io.ktor:ktor-server-netty:1.6.7") 29 | implementation("io.ktor:ktor-client-core:1.6.7") 30 | implementation("io.ktor:ktor-client-java:1.6.7") 31 | implementation("io.ktor:ktor-gson:1.6.7") 32 | 33 | compileOnly("com.velocitypowered:velocity-api:3.1.0") 34 | compileOnly("dev.cubxity.plugins:unifiedmetrics-api:0.3.4") 35 | kapt("com.velocitypowered:velocity-api:3.1.0") 36 | 37 | implementation(project(":common")) 38 | } 39 | 40 | tasks.test { 41 | useJUnitPlatform() 42 | } 43 | 44 | tasks.withType() { 45 | kotlinOptions.jvmTarget = "16" 46 | } 47 | 48 | tasks.build { 49 | dependsOn("shadowJar") 50 | } 51 | 52 | tasks { 53 | val shadowJar by getting(com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class) { 54 | archiveFileName.set("mycelium-${project.name}-${project.version}.jar") 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /operator/chart/templates/operator-statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: mycelium-operator 6 | name: mycelium-operator 7 | namespace: {{ .Release.Namespace }} 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: mycelium-operator 13 | template: 14 | metadata: 15 | annotations: 16 | prometheus.io/port: '8080' 17 | prometheus.io/scrape: 'true' 18 | labels: 19 | app: mycelium-operator 20 | spec: 21 | containers: 22 | - name: operator 23 | imagePullPolicy: {{ .Values.images.pullPolicy }} 24 | image: {{ tpl $.Values.images.operator $ }} 25 | env: 26 | - name: MYCELIUM_FW_TOKEN 27 | valueFrom: 28 | secretKeyRef: 29 | name: mycelium-operator 30 | key: forwarding_token 31 | - name: MYCELIUM_ENDPOINT 32 | value: mycelium-operator.{{ .Release.Namespace }}.svc.cluster.local:8080 33 | - name: MYCELIUM_RUNNER_IMAGE 34 | value: {{ tpl $.Values.images.runner $ }} 35 | - name: MYCELIUM_PLUGIN_VELOCITY 36 | value: {{ tpl $.Values.plugins.mycelium.velocity $ }} 37 | - name: MYCELIUM_PLUGIN_PAPER 38 | value: {{ tpl $.Values.plugins.mycelium.paper $ }} 39 | - name: METRICS_PLUGIN_VELOCITY 40 | value: {{ tpl $.Values.plugins.metrics.velocity $ }} 41 | - name: METRICS_PLUGIN_PAPER 42 | value: {{ tpl $.Values.plugins.metrics.paper $ }} 43 | ports: 44 | - containerPort: 8080 45 | name: api 46 | readinessProbe: 47 | httpGet: 48 | path: /health 49 | port: api 50 | initialDelaySeconds: 5 51 | periodSeconds: 5 52 | resources: 53 | limits: 54 | cpu: {{ .Values.resources.limits.cpu }} 55 | memory: {{ .Values.resources.limits.memory }} 56 | requests: 57 | cpu: {{ .Values.resources.requests.cpu }} 58 | memory: {{ .Values.resources.requests.memory }} 59 | serviceAccountName: mycelium-operator 60 | -------------------------------------------------------------------------------- /plugin/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /operator/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | use actix_web::{ 4 | get, middleware, 5 | web::{self, Data}, 6 | App, HttpRequest, HttpResponse, HttpServer, Responder, 7 | }; 8 | use mycelium::helpers::manager::Manager; 9 | pub use mycelium::*; 10 | use prometheus::{Encoder, TextEncoder}; 11 | use serde_json::json; 12 | use tracing::{info, warn}; 13 | use tracing_subscriber::{prelude::*, EnvFilter, Registry}; 14 | 15 | #[get("/metrics")] 16 | async fn metrics(c: Data, _req: HttpRequest) -> impl Responder { 17 | let metrics = c.metrics(); 18 | let encoder = TextEncoder::new(); 19 | let mut buffer = vec![]; 20 | encoder.encode(&metrics, &mut buffer).unwrap(); 21 | HttpResponse::Ok().body(buffer) 22 | } 23 | 24 | #[get("/health")] 25 | async fn health(_: HttpRequest) -> impl Responder { 26 | HttpResponse::Ok().body("healthy") 27 | } 28 | 29 | #[get("/state")] 30 | async fn state(c: Data, _req: HttpRequest) -> impl Responder { 31 | let state = c.state().await; 32 | HttpResponse::Ok().json(&state) 33 | } 34 | 35 | #[get("/servers/{ns}/{name}")] 36 | async fn servers(c: Data, path: web::Path<(String, String)>) -> actix_web::Result { 37 | let inner = path.into_inner(); 38 | let vec = c.get_sets(inner.0, inner.1).await?; 39 | Ok(HttpResponse::Ok().json(json!(vec))) 40 | } 41 | 42 | #[actix_rt::main] 43 | async fn main() -> Result<(), Error> { 44 | // Validate config 45 | env::var("MYCELIUM_FW_TOKEN")?; 46 | env::var("MYCELIUM_ENDPOINT")?; 47 | 48 | #[cfg(feature = "telemetry")] 49 | let otlp_endpoint = 50 | std::env::var("OPENTELEMETRY_ENDPOINT_URL")?; 51 | 52 | #[cfg(feature = "telemetry")] 53 | let tracer = opentelemetry_otlp::new_pipeline() 54 | .with_endpoint(&otlp_endpoint) 55 | .with_trace_config(opentelemetry::sdk::trace::config().with_resource( 56 | opentelemetry::sdk::Resource::new(vec![opentelemetry::KeyValue::new( 57 | "service.name", 58 | "mycelium-operator", 59 | )]), 60 | )) 61 | .with_tonic() 62 | .install_batch(opentelemetry::runtime::Tokio) 63 | .unwrap(); 64 | 65 | // Finish layers 66 | #[cfg(feature = "telemetry")] 67 | let telemetry = tracing_opentelemetry::layer().with_tracer(tracer); 68 | let logger = tracing_subscriber::fmt::layer().json(); 69 | 70 | let env_filter = EnvFilter::try_from_default_env() 71 | .or_else(|_| EnvFilter::try_new("info")) 72 | .unwrap(); 73 | 74 | // Register all subscribers 75 | #[cfg(feature = "telemetry")] 76 | let collector = Registry::default() 77 | .with(telemetry) 78 | .with(logger) 79 | .with(env_filter); 80 | #[cfg(not(feature = "telemetry"))] 81 | let collector = Registry::default().with(logger).with(env_filter); 82 | 83 | tracing::subscriber::set_global_default(collector).unwrap(); 84 | 85 | // Start kubernetes controller 86 | let (manager, set_drainer, proxy_drainer) = Manager::new().await; 87 | 88 | // Start web server 89 | let server = HttpServer::new(move || { 90 | App::new() 91 | .app_data(Data::new(manager.clone())) 92 | .wrap(middleware::Logger::default().exclude("/health")) 93 | .service(state) 94 | .service(servers) 95 | .service(health) 96 | .service(metrics) 97 | }) 98 | .bind("0.0.0.0:8080") 99 | .expect("can't bind to 0.0.0.0:8080") 100 | .shutdown_timeout(1); 101 | 102 | tokio::select! { 103 | _ = set_drainer => warn!("set_controller exited"), 104 | _ = proxy_drainer => warn!("proxy_controller exited"), 105 | _ = server.run() => info!("actix exited"), 106 | } 107 | Ok(()) 108 | } 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mycelium 2 | 3 | > 🌎 Deploy planet-scale Minecraft server networks on Kubernetes 4 | 5 | Mycelium is a Kubernetes controller that enables you to orchestrate and bridge together a large number of Minecraft servers--all with minimal required configuration. 6 | 7 | ## Installation 8 | 9 | > :warning: By default, any software with access to your internal cluster network has full control over your Minecraft servers. Work to stop this [is ongoing](https://github.com/nikhiljha/mycelium/issues/1), so you should not use mycelium unless you understand the consequences of this. 10 | 11 | ```bash 12 | helm repo add mycelium https://harbor.ocf.berkeley.edu/chartrepo/mycelium 13 | kubectl create ns mycelium 14 | helm install mycelium/mycelium -n mycelium 15 | ``` 16 | 17 | ## Usage 18 | 19 | Create MinecraftProxy CRDs representing proxies, and MinecraftSet CRDs representing servers. Below is a minimal example, but the full spec is available [in the docs](https://mycelium.njha.dev). 20 | 21 | > :warning: The `mycelium.njha.dev/v1beta1` apiVersion is unstable and may change from release to release, even across minor versions. It will, however, not change across patch versions. 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 50 | 79 | 80 |
MinecraftProxyMinecraftSet
30 | 31 | ```yaml 32 | kind: MinecraftProxy 33 | apiVersion: mycelium.njha.dev/v1beta1 34 | metadata: 35 | name: proxy 36 | spec: 37 | replicas: 1 38 | selector: 39 | matchLabels: 40 | mycelium.njha.dev/proxy: cluster 41 | runner: 42 | jar: 43 | type: velocity 44 | version: 3.1.2-SNAPSHOT 45 | build: "110" 46 | jvm: "-Xmx4G -Xms4G" 47 | ``` 48 | 49 | 51 | 52 | ```yaml 53 | kind: MinecraftSet 54 | apiVersion: mycelium.njha.dev/v1beta1 55 | metadata: 56 | name: testing 57 | labels: 58 | mycelium.njha.dev/proxy: cluster 59 | spec: 60 | replicas: 3 61 | runner: 62 | jar: 63 | type: paper 64 | version: 1.18.1 65 | build: "114" 66 | jvm: "-Xmx2G -Xms2G" 67 | container: 68 | volumeClaimTemplate: 69 | metadata: 70 | name: root 71 | spec: 72 | accessModes: ["ReadWriteOnce"] 73 | resources: 74 | requests: 75 | storage: 64Gi 76 | ``` 77 | 78 |
81 | 82 | ## Internals 83 | 84 | ### Components 85 | 86 | - `mycelium-operator` - A Kubernetes operator that listens for changes to `MinecraftSet` and `MinecraftProxy` CRDs and links them together by creating other Kubernetes objects (like `Service`, `StatefulSet`). 87 | - `mycelium-runner` - A Rust binary that acts as the entrypoint to proxy or game containers. It downloads server jars, plugins, and automatically edits configuration files to work how the operator expects. 88 | - `mycelium-velocity` - A Velocity plugin that 1) provides useful HTTP endpoints for `mycelium-operator` to interact with 2) pings `mycelium-operator` periodically to sync changes 3) collects monitoring information. 89 | - `mycelium-paper` - A PaperMC plugin that 1) exposes useful HTTP endpoints 2) collects monitoring information, exposing it to Kubernetes itself and `mycelium-operator`. 90 | 91 | ### Goals 92 | 93 | Keep in mind this project is in early alpha. This project doesn't meet very many of its goals yet, but, in no particular order... 94 | - cloud native monitoring, tracing, and observability 95 | - fault tolerance with redundant servers, proxies 96 | - (we're currently looking into dynamically moving players to a new endpoint, resulting in just a minor lag spike if an entire proxy goes down) 97 | - declarative, eventually-consistent server configuration 98 | - speed (minimal convergence time between cluster state and Minecraft state) 99 | - security (encryption backends for secrets, config management, rbac) 100 | -------------------------------------------------------------------------------- /operator/src/objects/minecraft_set.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | array::IntoIter, 3 | collections::{BTreeMap, HashMap}, 4 | iter::FromIterator, 5 | sync::Arc, 6 | }; 7 | 8 | use chrono::prelude::*; 9 | use futures::{future::BoxFuture, FutureExt, StreamExt}; 10 | use k8s_openapi::{ 11 | api::{ 12 | apps::v1::{StatefulSet, StatefulSetSpec}, 13 | core::v1::{ 14 | Container, EnvVar, PodSpec, PodTemplateSpec, ResourceRequirements, Service, 15 | ServicePort, ServiceSpec, Volume, VolumeMount, 16 | }, 17 | }, 18 | apimachinery::pkg::{ 19 | apis::meta::v1::{LabelSelector, ObjectMeta, OwnerReference}, 20 | util::intstr::IntOrString, 21 | }, 22 | }; 23 | use kube::{ 24 | api::{Api, ListParams, Patch, PatchParams, ResourceExt}, 25 | client::Client, 26 | CustomResource, Resource, 27 | }; 28 | use kube_runtime::controller::{Context, Controller, ReconcilerAction}; 29 | use maplit::hashmap; 30 | use prometheus::{ 31 | default_registry, proto::MetricFamily, register_histogram_vec, register_int_counter, 32 | HistogramOpts, HistogramVec, IntCounter, 33 | }; 34 | use schemars::JsonSchema; 35 | use serde::{Deserialize, Serialize}; 36 | use serde_json::json; 37 | use tokio::{ 38 | sync::RwLock, 39 | time::{Duration, Instant}, 40 | }; 41 | use tracing::{debug, error, event, field, info, instrument, trace, warn, Level, Span}; 42 | 43 | use crate::{ 44 | helpers::{jarapi::get_download_url, manager::Data, telemetry}, 45 | objects::{ 46 | generic_reconcile, make_volume, make_volume_mount, ConfigOptions, ContainerOptions, 47 | RunnerOptions, 48 | }, 49 | Error, Result, 50 | }; 51 | use crate::Error::MyceliumError; 52 | 53 | #[derive(CustomResource, Serialize, Deserialize, Default, Debug, PartialEq, Clone, JsonSchema)] 54 | #[kube( 55 | group = "mycelium.njha.dev", 56 | version = "v1beta1", 57 | kind = "MinecraftSet" 58 | )] 59 | #[kube(shortname = "mcset", namespaced)] 60 | pub struct MinecraftSetSpec { 61 | /// number of identical servers to create 62 | pub replicas: i32, 63 | 64 | /// options for the server runner 65 | pub runner: RunnerOptions, 66 | 67 | /// options for Kubernetes 68 | pub container: Option, 69 | 70 | /// options to pass to proxies that select this MinecraftSet 71 | pub proxy: Option, 72 | } 73 | 74 | #[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, JsonSchema)] 75 | pub struct ProxyOptions { 76 | /// configures the proxy to create a forced host for the MinecraftSet 77 | pub hostname: Option, 78 | 79 | /// priority for the default try = [] list, None means don't include in list 80 | pub priority: Option, 81 | } 82 | 83 | #[instrument(skip(ctx), fields(trace_id))] 84 | pub async fn reconcile(mcset: MinecraftSet, ctx: Context) -> Result { 85 | let trace_id = telemetry::get_trace_id(); 86 | Span::current().record("trace_id", &field::display(&trace_id)); 87 | let start = Instant::now(); 88 | 89 | let name = ResourceExt::name(&mcset); 90 | let ns = ResourceExt::namespace(&mcset) 91 | .ok_or_else(|| MyceliumError("failed to get namespace".into()))?; 92 | 93 | let mut plugin = vec![]; 94 | if let Ok(p) = std::env::var("MYCELIUM_PLUGIN_PAPER") { 95 | plugin.push(p) 96 | } 97 | if let Ok(p) = std::env::var("METRICS_PLUGIN_PAPER") { 98 | plugin.push(p) 99 | } 100 | 101 | generic_reconcile( 102 | vec![ 103 | EnvVar { 104 | name: String::from("MYCELIUM_RUNNER_KIND"), 105 | value: Some(String::from("game")), 106 | value_from: None, 107 | }, 108 | EnvVar { 109 | name: String::from("MYCELIUM_PLUGINS"), 110 | value: Some(mcset 111 | .spec 112 | .runner 113 | .plugins 114 | .clone() 115 | .unwrap_or_default() 116 | .into_iter() 117 | .chain(plugin.into_iter()) 118 | .collect::>().join(",")), 119 | value_from: None, 120 | }, 121 | ], 122 | IntOrString::Int(25565), 123 | ctx.clone(), 124 | "mcset".to_string(), 125 | mcset.clone(), 126 | mcset.spec.container.unwrap_or_default(), 127 | mcset.spec.runner, 128 | mcset.spec.replicas, 129 | ) 130 | .await?; 131 | 132 | let duration = start.elapsed().as_millis() as f64 / 1000.0; 133 | ctx.get_ref() 134 | .metrics 135 | .set_reconcile_duration 136 | .with_label_values(&[]) 137 | .observe(duration); 138 | ctx.get_ref().metrics.set_handled_events.inc(); 139 | info!("Reconciled MinecraftSet \"{}\" in {}", name, ns); 140 | 141 | // TODO: Do we need to check back if this succeeded & no changes were made? 142 | // i.e. Do we want to revert manual edits to StatefulSets or Services on a 143 | // timer? 144 | Ok(ReconcilerAction { 145 | requeue_after: None, 146 | }) 147 | } 148 | -------------------------------------------------------------------------------- /operator/src/objects/minecraft_proxy.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | array::IntoIter, 3 | collections::{BTreeMap, HashMap}, 4 | env, 5 | iter::FromIterator, 6 | sync::Arc, 7 | }; 8 | 9 | use chrono::prelude::*; 10 | use futures::{future::BoxFuture, FutureExt, StreamExt}; 11 | use k8s_openapi::{ 12 | api::{ 13 | apps::v1::{StatefulSet, StatefulSetSpec}, 14 | core::v1::{ 15 | Container, EnvVar, PodSpec, PodTemplateSpec, ResourceRequirements, Service, 16 | ServicePort, ServiceSpec, Volume, VolumeMount, 17 | }, 18 | }, 19 | apimachinery::pkg::{ 20 | apis::meta::v1::{LabelSelector, ObjectMeta, OwnerReference}, 21 | util::intstr::IntOrString, 22 | }, 23 | }; 24 | use k8s_openapi::api::core::v1::{EnvVarSource, ObjectFieldSelector}; 25 | use kube::{ 26 | api::{Api, ListParams, Patch, PatchParams, ResourceExt}, 27 | client::Client, 28 | CustomResource, Resource, 29 | }; 30 | use kube_runtime::controller::{Context, Controller, ReconcilerAction}; 31 | use maplit::hashmap; 32 | use prometheus::{ 33 | default_registry, proto::MetricFamily, register_histogram_vec, register_int_counter, 34 | HistogramOpts, HistogramVec, IntCounter, 35 | }; 36 | use schemars::JsonSchema; 37 | use serde::{Deserialize, Serialize}; 38 | use serde_json::json; 39 | use tokio::{ 40 | sync::RwLock, 41 | time::{Duration, Instant}, 42 | }; 43 | use tracing::{debug, error, event, field, info, instrument, trace, warn, Level, Span}; 44 | 45 | use crate::{ 46 | helpers::{jarapi::get_download_url, manager::Data, telemetry}, 47 | objects::{ 48 | generic_reconcile, make_volume, make_volume_mount, ConfigOptions, ContainerOptions, 49 | RunnerOptions, 50 | }, 51 | Error, Result, 52 | }; 53 | use crate::Error::MyceliumError; 54 | 55 | #[derive(CustomResource, Serialize, Deserialize, Default, Debug, PartialEq, Clone, JsonSchema)] 56 | #[kube( 57 | group = "mycelium.njha.dev", 58 | version = "v1beta1", 59 | kind = "MinecraftProxy", 60 | plural = "minecraftproxies" 61 | )] 62 | #[kube(shortname = "mcproxy", namespaced)] 63 | pub struct MinecraftProxySpec { 64 | /// number of identical proxies to create 65 | pub replicas: i32, 66 | 67 | /// options for the server runner 68 | pub runner: RunnerOptions, 69 | 70 | /// options for Kubernetes 71 | pub container: Option, 72 | 73 | /// what MinecraftSets to add to this proxy (only matchLabels is supported) 74 | pub selector: Option, 75 | } 76 | 77 | #[instrument(skip(ctx), fields(trace_id))] 78 | pub async fn reconcile( 79 | mcproxy: MinecraftProxy, 80 | ctx: Context, 81 | ) -> Result { 82 | let trace_id = telemetry::get_trace_id(); 83 | Span::current().record("trace_id", &field::display(&trace_id)); 84 | let start = Instant::now(); 85 | 86 | let name = ResourceExt::name(&mcproxy); 87 | let ns = ResourceExt::namespace(&mcproxy) 88 | .ok_or_else(|| MyceliumError("failed to get namespace".into()))?; 89 | 90 | let mut plugin = vec![]; 91 | if let Ok(p) = env::var("MYCELIUM_PLUGIN_VELOCITY") { 92 | plugin.push(p) 93 | } 94 | if let Ok(p) = env::var("METRICS_PLUGIN_VELOCITY") { 95 | plugin.push(p) 96 | } 97 | 98 | generic_reconcile( 99 | vec![ 100 | EnvVar { 101 | name: String::from("MYCELIUM_RUNNER_KIND"), 102 | value: Some(String::from("proxy")), 103 | value_from: None, 104 | }, 105 | EnvVar { 106 | name: String::from("MYCELIUM_PLUGINS"), 107 | value: Some(mcproxy 108 | .spec 109 | .runner 110 | .plugins 111 | .clone() 112 | .unwrap_or_default() 113 | .into_iter() 114 | .chain(plugin.into_iter()) 115 | .collect::>().join(",")), 116 | value_from: None, 117 | }, 118 | EnvVar { 119 | name: String::from("MYCELIUM_ENDPOINT"), 120 | value: Some(env::var("MYCELIUM_ENDPOINT").unwrap()), 121 | value_from: None, 122 | }, 123 | EnvVar { 124 | name: String::from("K8S_NAMESPACE"), 125 | value: None, 126 | value_from: Some(EnvVarSource { 127 | field_ref: Some(ObjectFieldSelector { 128 | api_version: None, 129 | field_path: "metadata.namespace".to_string() 130 | }), 131 | ..EnvVarSource::default() 132 | }), 133 | }, 134 | EnvVar { 135 | name: String::from("K8S_NAME"), 136 | value: Some(name.clone()), 137 | value_from: None, 138 | }, 139 | ], 140 | IntOrString::Int(25577), 141 | ctx.clone(), 142 | "mcproxy".to_string(), 143 | mcproxy.clone(), 144 | mcproxy.spec.container.unwrap_or_default(), 145 | mcproxy.spec.runner, 146 | mcproxy.spec.replicas, 147 | ) 148 | .await?; 149 | 150 | let duration = start.elapsed().as_millis() as f64 / 1000.0; 151 | ctx.get_ref() 152 | .metrics 153 | .proxy_reconcile_duration 154 | .with_label_values(&[]) 155 | .observe(duration); 156 | ctx.get_ref().metrics.proxy_handled_events.inc(); 157 | info!("Reconciled MinecraftProxy \"{}\" in {}", name, ns); 158 | 159 | Ok(ReconcilerAction { 160 | requeue_after: None, 161 | }) 162 | } 163 | -------------------------------------------------------------------------------- /plugin/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /plugin/velocity/.gitignore: -------------------------------------------------------------------------------- 1 | ### Intellij ### 2 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 3 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 4 | 5 | # User-specific stuff 6 | .idea/**/workspace.xml 7 | .idea/**/tasks.xml 8 | .idea/**/usage.statistics.xml 9 | .idea/**/dictionaries 10 | .idea/**/shelf 11 | 12 | # Generated files 13 | .idea/**/contentModel.xml 14 | 15 | # Sensitive or high-churn files 16 | .idea/**/dataSources/ 17 | .idea/**/dataSources.ids 18 | .idea/**/dataSources.local.xml 19 | .idea/**/sqlDataSources.xml 20 | .idea/**/dynamic.xml 21 | .idea/**/uiDesigner.xml 22 | .idea/**/dbnavigator.xml 23 | 24 | # Gradle 25 | .idea/**/gradle.xml 26 | .idea/**/libraries 27 | 28 | # Gradle and Maven with auto-import 29 | # When using Gradle or Maven with auto-import, you should exclude module files, 30 | # since they will be recreated, and may cause churn. Uncomment if using 31 | # auto-import. 32 | # .idea/artifacts 33 | # .idea/compiler.xml 34 | # .idea/jarRepositories.xml 35 | # .idea/modules.xml 36 | # .idea/*.iml 37 | # .idea/modules 38 | # *.iml 39 | # *.ipr 40 | 41 | # CMake 42 | cmake-build-*/ 43 | 44 | # Mongo Explorer plugin 45 | .idea/**/mongoSettings.xml 46 | 47 | # File-based project format 48 | *.iws 49 | 50 | # IntelliJ 51 | out/ 52 | 53 | # mpeltonen/sbt-idea plugin 54 | .idea_modules/ 55 | 56 | # JIRA plugin 57 | atlassian-ide-plugin.xml 58 | 59 | # Cursive Clojure plugin 60 | .idea/replstate.xml 61 | 62 | # Crashlytics plugin (for Android Studio and IntelliJ) 63 | com_crashlytics_export_strings.xml 64 | crashlytics.properties 65 | crashlytics-build.properties 66 | fabric.properties 67 | 68 | # Editor-based Rest Client 69 | .idea/httpRequests 70 | 71 | # Android studio 3.1+ serialized cache file 72 | .idea/caches/build_file_checksums.ser 73 | 74 | ### Intellij Patch ### 75 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 76 | 77 | # *.iml 78 | # modules.xml 79 | # .idea/misc.xml 80 | # *.ipr 81 | 82 | # Sonarlint plugin 83 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 84 | .idea/**/sonarlint/ 85 | 86 | # SonarQube Plugin 87 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 88 | .idea/**/sonarIssues.xml 89 | 90 | # Markdown Navigator plugin 91 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 92 | .idea/**/markdown-navigator.xml 93 | .idea/**/markdown-navigator-enh.xml 94 | .idea/**/markdown-navigator/ 95 | 96 | # Cache file creation bug 97 | # See https://youtrack.jetbrains.com/issue/JBR-2257 98 | .idea/$CACHE_FILE$ 99 | 100 | # CodeStream plugin 101 | # https://plugins.jetbrains.com/plugin/12206-codestream 102 | .idea/codestream.xml 103 | 104 | ### Intellij+all ### 105 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 106 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 107 | 108 | # User-specific stuff 109 | 110 | # Generated files 111 | 112 | # Sensitive or high-churn files 113 | 114 | # Gradle 115 | 116 | # Gradle and Maven with auto-import 117 | # When using Gradle or Maven with auto-import, you should exclude module files, 118 | # since they will be recreated, and may cause churn. Uncomment if using 119 | # auto-import. 120 | # .idea/artifacts 121 | # .idea/compiler.xml 122 | # .idea/jarRepositories.xml 123 | # .idea/modules.xml 124 | # .idea/*.iml 125 | # .idea/modules 126 | # *.iml 127 | # *.ipr 128 | 129 | # CMake 130 | 131 | # Mongo Explorer plugin 132 | 133 | # File-based project format 134 | 135 | # IntelliJ 136 | 137 | # mpeltonen/sbt-idea plugin 138 | 139 | # JIRA plugin 140 | 141 | # Cursive Clojure plugin 142 | 143 | # Crashlytics plugin (for Android Studio and IntelliJ) 144 | 145 | # Editor-based Rest Client 146 | 147 | # Android studio 3.1+ serialized cache file 148 | 149 | ### Intellij+all Patch ### 150 | # Ignores the whole .idea folder and all .iml files 151 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 152 | 153 | .idea/ 154 | 155 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 156 | 157 | *.iml 158 | modules.xml 159 | .idea/misc.xml 160 | *.ipr 161 | 162 | # Sonarlint plugin 163 | .idea/sonarlint 164 | 165 | ### Intellij+iml ### 166 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 167 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 168 | 169 | # User-specific stuff 170 | 171 | # Generated files 172 | 173 | # Sensitive or high-churn files 174 | 175 | # Gradle 176 | 177 | # Gradle and Maven with auto-import 178 | # When using Gradle or Maven with auto-import, you should exclude module files, 179 | # since they will be recreated, and may cause churn. Uncomment if using 180 | # auto-import. 181 | # .idea/artifacts 182 | # .idea/compiler.xml 183 | # .idea/jarRepositories.xml 184 | # .idea/modules.xml 185 | # .idea/*.iml 186 | # .idea/modules 187 | # *.iml 188 | # *.ipr 189 | 190 | # CMake 191 | 192 | # Mongo Explorer plugin 193 | 194 | # File-based project format 195 | 196 | # IntelliJ 197 | 198 | # mpeltonen/sbt-idea plugin 199 | 200 | # JIRA plugin 201 | 202 | # Cursive Clojure plugin 203 | 204 | # Crashlytics plugin (for Android Studio and IntelliJ) 205 | 206 | # Editor-based Rest Client 207 | 208 | # Android studio 3.1+ serialized cache file 209 | 210 | ### Intellij+iml Patch ### 211 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 212 | 213 | 214 | ### Java ### 215 | # Compiled class file 216 | *.class 217 | 218 | # Log file 219 | *.log 220 | 221 | # BlueJ files 222 | *.ctxt 223 | 224 | # Mobile Tools for Java (J2ME) 225 | .mtj.tmp/ 226 | 227 | # Package Files # 228 | *.jar 229 | *.war 230 | *.nar 231 | *.ear 232 | *.zip 233 | *.tar.gz 234 | *.rar 235 | 236 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 237 | hs_err_pid* 238 | 239 | ### Kotlin ### 240 | # Compiled class file 241 | 242 | # Log file 243 | 244 | # BlueJ files 245 | 246 | # Mobile Tools for Java (J2ME) 247 | 248 | # Package Files # 249 | 250 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 251 | 252 | ### Maven ### 253 | target/ 254 | pom.xml.tag 255 | pom.xml.releaseBackup 256 | pom.xml.versionsBackup 257 | pom.xml.next 258 | release.properties 259 | dependency-reduced-pom.xml 260 | buildNumber.properties 261 | .mvn/timing.properties 262 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 263 | .mvn/wrapper/maven-wrapper.jar 264 | 265 | ### Gradle ### 266 | .gradle 267 | build/ 268 | 269 | # Ignore Gradle GUI config 270 | gradle-app.setting 271 | 272 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 273 | !gradle-wrapper.jar 274 | 275 | # Cache of project 276 | .gradletasknamecache 277 | 278 | ### Gradle Patch ### 279 | **/build/ 280 | 281 | ### Other autogenerated things 282 | # some people said you should commit this to git but I don't believe them 283 | /gradle/wrapper 284 | /gradlew 285 | -------------------------------------------------------------------------------- /plugin/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/intellij,gradle,forgegradle,java,kotlin,intellij+all,intellij+iml 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=intellij,gradle,forgegradle,java,kotlin,intellij+all,intellij+iml 4 | 5 | ### ForgeGradle ### 6 | # Minecraft client/server files 7 | run/ 8 | 9 | ### Intellij ### 10 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 11 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 12 | 13 | # User-specific stuff 14 | .idea/**/workspace.xml 15 | .idea/**/tasks.xml 16 | .idea/**/usage.statistics.xml 17 | .idea/**/dictionaries 18 | .idea/**/shelf 19 | 20 | # AWS User-specific 21 | .idea/**/aws.xml 22 | 23 | # Generated files 24 | .idea/**/contentModel.xml 25 | 26 | # Sensitive or high-churn files 27 | .idea/**/dataSources/ 28 | .idea/**/dataSources.ids 29 | .idea/**/dataSources.local.xml 30 | .idea/**/sqlDataSources.xml 31 | .idea/**/dynamic.xml 32 | .idea/**/uiDesigner.xml 33 | .idea/**/dbnavigator.xml 34 | 35 | # Gradle 36 | .idea/**/gradle.xml 37 | .idea/**/libraries 38 | 39 | # Gradle and Maven with auto-import 40 | # When using Gradle or Maven with auto-import, you should exclude module files, 41 | # since they will be recreated, and may cause churn. Uncomment if using 42 | # auto-import. 43 | # .idea/artifacts 44 | # .idea/compiler.xml 45 | # .idea/jarRepositories.xml 46 | # .idea/modules.xml 47 | # .idea/*.iml 48 | # .idea/modules 49 | # *.iml 50 | # *.ipr 51 | 52 | # CMake 53 | cmake-build-*/ 54 | 55 | # Mongo Explorer plugin 56 | .idea/**/mongoSettings.xml 57 | 58 | # File-based project format 59 | *.iws 60 | 61 | # IntelliJ 62 | out/ 63 | 64 | # mpeltonen/sbt-idea plugin 65 | .idea_modules/ 66 | 67 | # JIRA plugin 68 | atlassian-ide-plugin.xml 69 | 70 | # Cursive Clojure plugin 71 | .idea/replstate.xml 72 | 73 | # Crashlytics plugin (for Android Studio and IntelliJ) 74 | com_crashlytics_export_strings.xml 75 | crashlytics.properties 76 | crashlytics-build.properties 77 | fabric.properties 78 | 79 | # Editor-based Rest Client 80 | .idea/httpRequests 81 | 82 | # Android studio 3.1+ serialized cache file 83 | .idea/caches/build_file_checksums.ser 84 | 85 | ### Intellij Patch ### 86 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 87 | 88 | # *.iml 89 | # modules.xml 90 | # .idea/misc.xml 91 | # *.ipr 92 | 93 | # Sonarlint plugin 94 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 95 | .idea/**/sonarlint/ 96 | 97 | # SonarQube Plugin 98 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 99 | .idea/**/sonarIssues.xml 100 | 101 | # Markdown Navigator plugin 102 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 103 | .idea/**/markdown-navigator.xml 104 | .idea/**/markdown-navigator-enh.xml 105 | .idea/**/markdown-navigator/ 106 | 107 | # Cache file creation bug 108 | # See https://youtrack.jetbrains.com/issue/JBR-2257 109 | .idea/$CACHE_FILE$ 110 | 111 | # CodeStream plugin 112 | # https://plugins.jetbrains.com/plugin/12206-codestream 113 | .idea/codestream.xml 114 | 115 | ### Intellij+all ### 116 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 117 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 118 | 119 | # User-specific stuff 120 | 121 | # AWS User-specific 122 | 123 | # Generated files 124 | 125 | # Sensitive or high-churn files 126 | 127 | # Gradle 128 | 129 | # Gradle and Maven with auto-import 130 | # When using Gradle or Maven with auto-import, you should exclude module files, 131 | # since they will be recreated, and may cause churn. Uncomment if using 132 | # auto-import. 133 | # .idea/artifacts 134 | # .idea/compiler.xml 135 | # .idea/jarRepositories.xml 136 | # .idea/modules.xml 137 | # .idea/*.iml 138 | # .idea/modules 139 | # *.iml 140 | # *.ipr 141 | 142 | # CMake 143 | 144 | # Mongo Explorer plugin 145 | 146 | # File-based project format 147 | 148 | # IntelliJ 149 | 150 | # mpeltonen/sbt-idea plugin 151 | 152 | # JIRA plugin 153 | 154 | # Cursive Clojure plugin 155 | 156 | # Crashlytics plugin (for Android Studio and IntelliJ) 157 | 158 | # Editor-based Rest Client 159 | 160 | # Android studio 3.1+ serialized cache file 161 | 162 | ### Intellij+all Patch ### 163 | # Ignores the whole .idea folder and all .iml files 164 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 165 | 166 | .idea/ 167 | 168 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 169 | 170 | *.iml 171 | modules.xml 172 | .idea/misc.xml 173 | *.ipr 174 | 175 | # Sonarlint plugin 176 | .idea/sonarlint 177 | 178 | ### Intellij+iml ### 179 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 180 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 181 | 182 | # User-specific stuff 183 | 184 | # AWS User-specific 185 | 186 | # Generated files 187 | 188 | # Sensitive or high-churn files 189 | 190 | # Gradle 191 | 192 | # Gradle and Maven with auto-import 193 | # When using Gradle or Maven with auto-import, you should exclude module files, 194 | # since they will be recreated, and may cause churn. Uncomment if using 195 | # auto-import. 196 | # .idea/artifacts 197 | # .idea/compiler.xml 198 | # .idea/jarRepositories.xml 199 | # .idea/modules.xml 200 | # .idea/*.iml 201 | # .idea/modules 202 | # *.iml 203 | # *.ipr 204 | 205 | # CMake 206 | 207 | # Mongo Explorer plugin 208 | 209 | # File-based project format 210 | 211 | # IntelliJ 212 | 213 | # mpeltonen/sbt-idea plugin 214 | 215 | # JIRA plugin 216 | 217 | # Cursive Clojure plugin 218 | 219 | # Crashlytics plugin (for Android Studio and IntelliJ) 220 | 221 | # Editor-based Rest Client 222 | 223 | # Android studio 3.1+ serialized cache file 224 | 225 | ### Intellij+iml Patch ### 226 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 227 | 228 | 229 | ### Java ### 230 | # Compiled class file 231 | *.class 232 | 233 | # Log file 234 | *.log 235 | 236 | # BlueJ files 237 | *.ctxt 238 | 239 | # Mobile Tools for Java (J2ME) 240 | .mtj.tmp/ 241 | 242 | # Package Files # 243 | *.jar 244 | *.war 245 | *.nar 246 | *.ear 247 | *.zip 248 | *.tar.gz 249 | *.rar 250 | 251 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 252 | hs_err_pid* 253 | 254 | ### Kotlin ### 255 | # Compiled class file 256 | 257 | # Log file 258 | 259 | # BlueJ files 260 | 261 | # Mobile Tools for Java (J2ME) 262 | 263 | # Package Files # 264 | 265 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 266 | 267 | ### Gradle ### 268 | .gradle 269 | build/ 270 | 271 | # Ignore Gradle GUI config 272 | gradle-app.setting 273 | 274 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 275 | !gradle-wrapper.jar 276 | 277 | # Cache of project 278 | .gradletasknamecache 279 | 280 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 281 | # gradle/wrapper/gradle-wrapper.properties 282 | 283 | ### Gradle Patch ### 284 | **/build/ 285 | 286 | # Eclipse Gradle plugin generated files 287 | # Eclipse Core 288 | .project 289 | # JDT-specific (Eclipse Java Development Tools) 290 | .classpath 291 | 292 | # End of https://www.toptal.com/developers/gitignore/api/intellij,gradle,forgegradle,java,kotlin,intellij+all,intellij+iml 293 | 294 | gradle/ 295 | -------------------------------------------------------------------------------- /operator/src/helpers/manager.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | env, 3 | sync::{Arc, RwLock}, 4 | time::Duration, 5 | }; 6 | use actix_web::body::BoxBody; 7 | 8 | use futures::{future::BoxFuture, FutureExt, StreamExt}; 9 | use k8s_openapi::api::apps::v1::StatefulSet; 10 | use k8s_openapi::api::core::v1::{Secret, Service}; 11 | use kube::{api::ListParams, Api, Client}; 12 | use kube_runtime::{ 13 | controller::{Context, ReconcilerAction}, 14 | Controller, 15 | }; 16 | use prometheus::{default_registry, proto::MetricFamily}; 17 | use serde::{Deserialize, Serialize}; 18 | use tracing::{info, warn}; 19 | 20 | use crate::{ 21 | helpers::{metrics::Metrics, state::State}, 22 | objects, 23 | objects::{ 24 | minecraft_proxy::MinecraftProxy, 25 | minecraft_set::{MinecraftSet, MinecraftSetSpec}, 26 | }, 27 | Error, 28 | }; 29 | use crate::objects::minecraft_proxy::MinecraftProxySpec; 30 | 31 | /// a manager that owns a Controller 32 | #[derive(Clone)] 33 | pub struct Manager { 34 | /// in memory state 35 | state: Arc>, 36 | /// prometheus metrics 37 | metrics: Metrics, 38 | /// kube api 39 | client: Client, 40 | } 41 | 42 | impl Manager { 43 | /// lifecycle interface for mycelium CRDs returns both (a `Manager`, a 44 | /// future to be awaited) `fn main()` will await the future, exiting when 45 | /// this future returns 46 | pub async fn new() -> (Self, BoxFuture<'static, ()>, BoxFuture<'static, ()>) { 47 | let client = Client::try_default().await.expect("create client"); 48 | let metrics = Metrics::new(); 49 | let state = Arc::new(RwLock::new(State::new())); 50 | 51 | // setup configuration and state data 52 | let data = Data { 53 | client: client.clone(), 54 | metrics: metrics.clone(), 55 | state: state.clone(), 56 | config: MyceliumConfig { 57 | forwarding_secret: env::var("MYCELIUM_FW_TOKEN").unwrap(), 58 | runner_image: env::var("MYCELIUM_RUNNER_IMAGE").unwrap(), 59 | }, 60 | }; 61 | let set_context = Context::new(data.clone()); 62 | let proxy_context = Context::new(data.clone()); 63 | 64 | // APIs to watch 65 | let mcsets = Api::::all(client.clone()); 66 | let mcproxies = Api::::all(client.clone()); 67 | let statesets = Api::::all(client.clone()); 68 | let secrets = Api::::all(client.clone()); 69 | let services = Api::::all(client.clone()); 70 | 71 | // ensure CRD is installed 72 | mcsets.list(&ListParams::default().limit(1)).await.expect( 73 | "are the crds installed? install them with: mycelium-crdgen | kubectl apply -f -", 74 | ); 75 | 76 | // return the controller 77 | let set_controller = Controller::new(mcsets, ListParams::default()) 78 | .owns(statesets.clone(), ListParams::default()) 79 | .owns(secrets.clone(), ListParams::default()) 80 | .owns(services.clone(), ListParams::default()) 81 | .run( 82 | crate::objects::minecraft_set::reconcile, 83 | error_policy, 84 | set_context, 85 | ) 86 | .for_each(|res| async move { 87 | match res { 88 | Ok(o) => info!("reconciled {:?}", o), 89 | Err(e) => warn!("reconcile failed: {}", e), 90 | } 91 | }) 92 | .boxed(); 93 | 94 | let proxy_controller = Controller::new(mcproxies, ListParams::default()) 95 | .owns(statesets.clone(), ListParams::default()) 96 | .owns(secrets.clone(), ListParams::default()) 97 | .owns(services.clone(), ListParams::default()) 98 | .run( 99 | crate::objects::minecraft_proxy::reconcile, 100 | error_policy, 101 | proxy_context, 102 | ) 103 | .for_each(|res| async move { 104 | match res { 105 | Ok(o) => info!("reconciled {:?}", o), 106 | Err(e) => warn!("reconcile failed: {}", e), 107 | } 108 | }) 109 | .boxed(); 110 | 111 | ( 112 | Self { 113 | state, 114 | metrics, 115 | client: client.clone(), 116 | }, 117 | set_controller, 118 | proxy_controller, 119 | ) 120 | } 121 | 122 | /// metrics getter 123 | pub fn metrics(&self) -> Vec { 124 | default_registry().gather() 125 | } 126 | 127 | /// state getter 128 | pub async fn state(&self) -> State { 129 | self.state.read().expect("state getter").clone() 130 | } 131 | 132 | /// velocity server getter 133 | pub async fn get_sets(&self, ns: String, name: String) -> Result, Error> { 134 | let proxy_api: Api = Api::namespaced(self.client.clone(), &ns); 135 | let proxy: MinecraftProxy = proxy_api.get(&name).await?; 136 | let proxy_spec: MinecraftProxySpec = proxy.spec; 137 | 138 | let label_selector = proxy_spec.selector.unwrap_or_default() 139 | .match_labels.unwrap_or_default() 140 | .iter().map(|i| format!("{}={}", i.0, i.1)) 141 | .collect::>().join(","); 142 | 143 | let mcset_api: Api = Api::namespaced(self.client.clone(), &ns); 144 | let objects = mcset_api.list(&ListParams::default().labels(&label_selector)).await?; 145 | 146 | Ok(objects.items.iter().flat_map(|set: &MinecraftSet| { 147 | let spec: &MinecraftSetSpec = &set.spec; 148 | let proxy = spec.proxy.clone().unwrap_or_default(); 149 | (0..spec.replicas) 150 | .map(move |val| -> VelocityServerEntry { 151 | VelocityServerEntry { 152 | address: format!( 153 | "{0}-{1}.{0}.{2}.svc.cluster.local", 154 | set.metadata.name.clone().unwrap(), 155 | val, 156 | set.metadata.namespace.clone().unwrap() 157 | ), 158 | host: proxy.hostname.clone(), 159 | name: format!("{}-{}", set.metadata.name.clone().unwrap(), val), 160 | priority: proxy.priority, 161 | } 162 | }) 163 | }).collect()) 164 | } 165 | } 166 | 167 | pub fn error_policy(error: &Error, _ctx: Context) -> ReconcilerAction { 168 | warn!("reconcile failed: {:?}", error); 169 | ReconcilerAction { 170 | requeue_after: Some(Duration::from_secs(360)), 171 | } 172 | } 173 | 174 | #[derive(Serialize, Deserialize, Default, Debug, Clone)] 175 | pub struct VelocityServerEntry { 176 | /// IP Address or DNS Name of minecraft server 177 | pub address: String, 178 | /// optional forced host 179 | pub host: Option, 180 | /// unique name for server 181 | pub name: String, 182 | /// priority for default list 183 | pub priority: Option, 184 | } 185 | 186 | #[derive(Clone)] 187 | pub struct MyceliumConfig { 188 | /// velocity forwarding secret 189 | pub(crate) forwarding_secret: String, 190 | /// runner image 191 | pub(crate) runner_image: String, 192 | } 193 | 194 | #[derive(Clone)] 195 | pub struct Data { 196 | /// kubernetes API client 197 | pub(crate) client: Client, 198 | /// in memory state 199 | pub(crate) state: Arc>, 200 | /// prometheus metrics 201 | pub(crate) metrics: Metrics, 202 | /// parsed configuration 203 | pub(crate) config: MyceliumConfig, 204 | } 205 | -------------------------------------------------------------------------------- /operator/src/runner.rs: -------------------------------------------------------------------------------- 1 | use std::{env, fs::{create_dir_all, read_to_string, File}, io::{Error, Write}, path::Path, process::{Command, Stdio}, thread}; 2 | use std::path::PathBuf; 3 | 4 | use linked_hash_map::LinkedHashMap; 5 | use nix::libc::pid_t; 6 | use nix::sys::signal; 7 | use nix::unistd::Pid; 8 | use signal_hook::consts::{SIGINT, SIGTERM}; 9 | use signal_hook::iterator::Signals; 10 | use toml_edit::{value, Array, Document, Table}; 11 | use yaml_rust::{Yaml, YamlEmitter, YamlLoader}; 12 | 13 | fn main() -> Result<(), Error> { 14 | let config_path = env::var("MYCELIUM_CONFIG_PATH").unwrap_or_else(|_| String::from("/config")); 15 | let data_path = env::var("MYCELIUM_DATA_PATH").unwrap_or_else(|_| String::from("/data")); 16 | let fw_token = env::var("MYCELIUM_FW_TOKEN").unwrap(); 17 | let server_kind = env::var("MYCELIUM_RUNNER_KIND").unwrap(); 18 | 19 | // create paths from env vars 20 | let config_path: &Path = Path::new(&config_path); 21 | let data_path: &Path = Path::new(&data_path); 22 | 23 | assert!(config_path.is_dir()); 24 | assert!(data_path.is_dir()); 25 | 26 | // copy all the files from config_path to data_path 27 | // TODO: rewrite properly without Command 28 | Command::new("sh") 29 | .args(&[ 30 | "-c", 31 | &format!( 32 | "cp {}/* {}", 33 | config_path.to_str().unwrap(), 34 | data_path.to_str().unwrap() 35 | ), 36 | ]) 37 | .output() 38 | .expect("failed to copy configuration"); 39 | 40 | // configure the server 41 | match server_kind.as_str() { 42 | "game" => configure_game(fw_token, data_path), 43 | "proxy" => configure_proxy(fw_token, data_path), 44 | _ => panic!("env::var(MYCELIUM_RUNNER_KIND) must be 'game' or 'proxy'"), 45 | }?; 46 | 47 | // download plugins 48 | download_plugins(data_path)?; 49 | 50 | // configure metrics 51 | configure_metrics(data_path)?; 52 | 53 | // start server 54 | download_run_server(data_path)?; 55 | 56 | Ok(()) 57 | } 58 | 59 | fn download_file(url: &str, path: PathBuf) { 60 | if path.exists() { 61 | println!("skipping {}", url); 62 | return 63 | } 64 | println!("downloading {}", url); 65 | let path_str = path.to_str().unwrap(); 66 | Command::new("curl") 67 | .args(&["-L", url, "--output", path_str]) 68 | .stdout(Stdio::inherit()) 69 | .stderr(Stdio::inherit()) 70 | .spawn() 71 | .expect("exec download") 72 | .wait() 73 | .expect("wait for download"); 74 | } 75 | 76 | fn run_jar(cwd: &str, file: &str) { 77 | let jvm_opts = env::var("MYCELIUM_JVM_OPTS").unwrap_or_else(|_| "".into()); 78 | let args: Vec<&str> = jvm_opts 79 | .split_terminator(' ') 80 | .chain(vec!["-jar", file].into_iter()) 81 | .collect(); 82 | 83 | let mut signals = Signals::new(&[SIGTERM, SIGINT]).unwrap(); 84 | let mut minecraft = Command::new("java") 85 | .args(args) 86 | .current_dir(cwd) 87 | .stdin(Stdio::inherit()) 88 | .stdout(Stdio::inherit()) 89 | .stderr(Stdio::inherit()) 90 | .spawn() 91 | .expect("run jar"); 92 | 93 | let id = minecraft.id(); 94 | let handle = signals.handle(); 95 | thread::spawn(move || { 96 | for _ in signals.forever() { 97 | println!("[runner] Caught interrupt, sending sigterm to java..."); 98 | signal::kill(Pid::from_raw(id as pid_t), nix::sys::signal::Signal::SIGTERM) 99 | .expect("can't kill java"); 100 | } 101 | }); 102 | 103 | minecraft.wait() 104 | .expect("wait for jar"); 105 | handle.close(); 106 | } 107 | 108 | fn download_plugins(data_path: &Path) -> Result<(), Error> { 109 | let plugins_str = env::var("MYCELIUM_PLUGINS").unwrap_or_else(|_| "".into()); 110 | let plugins = plugins_str.split_terminator(','); 111 | let plugin_dir_path = data_path.join("plugins/"); 112 | let plugin_dir = plugin_dir_path.to_str().unwrap(); 113 | create_dir_all(plugin_dir)?; 114 | for p in plugins { 115 | let file = p.split('/').last().unwrap(); 116 | let plugin_path = plugin_dir_path.join(file); 117 | download_file(p, plugin_path); 118 | } 119 | Ok(()) 120 | } 121 | 122 | fn download_run_server(data_path: &Path) -> Result<(), Error> { 123 | let url = env::var("MYCELIUM_RUNNER_JAR_URL").unwrap(); 124 | let data_path_str = data_path.to_str().unwrap(); 125 | let file = url.split('/').last().unwrap(); 126 | let paper_jar_path = data_path.join(file); 127 | download_file(&url, paper_jar_path); 128 | run_jar(data_path_str, file); 129 | 130 | Ok(()) 131 | } 132 | 133 | // the yaml parsing and modification in this function is horrifying 134 | // maybe I should've just written go 135 | fn configure_game(token: String, data_path: &Path) -> Result<(), Error> { 136 | let paper_yaml_path = data_path.join("paper.yml"); 137 | let paper_yaml: String = match read_to_string(paper_yaml_path.clone()) { 138 | Ok(file) => file, 139 | Err(_error) => include_str!("../defaults/paper.yml").to_string(), 140 | }; 141 | let loaded = YamlLoader::load_from_str(&paper_yaml).expect("YAML parse"); 142 | let mut yaml_doc = loaded[0].as_hash().unwrap().clone(); 143 | 144 | // modify the config 145 | let mut settings = yaml_doc[&Yaml::from_str("settings")] 146 | .as_hash() 147 | .unwrap() 148 | .clone(); 149 | let mut velocity_map = LinkedHashMap::new(); 150 | velocity_map.insert(Yaml::from_str("enabled"), Yaml::Boolean(true)); 151 | velocity_map.insert(Yaml::from_str("online-mode"), Yaml::Boolean(true)); 152 | velocity_map.insert(Yaml::from_str("secret"), Yaml::from_str(&token)); 153 | settings[&Yaml::from_str("velocity-support")] = Yaml::Hash(velocity_map); 154 | yaml_doc[&Yaml::from_str("settings")] = Yaml::Hash(settings); 155 | let yamled = Yaml::Hash(yaml_doc); 156 | 157 | // accept the EULA 158 | let eula_txt_path = data_path.join("eula.txt"); 159 | let mut f = File::create(eula_txt_path)?; 160 | f.write_all("eula=true".as_bytes())?; 161 | 162 | // write server props if dne 163 | match read_to_string(data_path.join("server.properties")) { 164 | Ok(_) => {} 165 | Err(_) => { 166 | let mut f = File::create(data_path.join("server.properties"))?; 167 | f.write_all(include_str!("../defaults/server.properties").as_bytes())?; 168 | } 169 | } 170 | 171 | // write the modified config 172 | let mut f = File::create(paper_yaml_path)?; 173 | let mut out_str = String::new(); 174 | let mut emitter = YamlEmitter::new(&mut out_str); 175 | emitter.dump(&yamled).unwrap(); 176 | f.write_all(out_str.as_bytes())?; 177 | Ok(()) 178 | } 179 | 180 | fn configure_proxy(token: String, data_path: &Path) -> Result<(), Error> { 181 | // read and parse velocity.toml 182 | let velocity_toml_path = data_path.join("velocity.toml"); 183 | let velocity_toml: String = match read_to_string(velocity_toml_path.clone()) { 184 | Ok(file) => file, 185 | Err(_error) => include_str!("../defaults/velocity.toml").to_string(), 186 | }; 187 | let mut toml_doc = velocity_toml.parse::().expect("TOML parse"); 188 | 189 | // modify the config 190 | toml_doc["forwarding-secret"] = value(token); 191 | let mut servers = Table::default(); 192 | servers["try"] = value(Array::default()); 193 | toml_doc["servers"] = toml_edit::Item::Table(servers); 194 | 195 | // write the modified config 196 | let mut f = File::create(velocity_toml_path)?; 197 | f.write_all(toml_doc.to_string().as_bytes())?; 198 | Ok(()) 199 | } 200 | 201 | fn configure_metrics(data_path: &Path) -> Result<(), Error> { 202 | let config_path = data_path.join("plugins/UnifiedMetrics/driver"); 203 | create_dir_all(config_path.clone())?; 204 | let prom_path = config_path.join("prometheus.yml"); 205 | if !prom_path.exists() { 206 | let mut f = File::create(prom_path)?; 207 | f.write_all(include_str!("../defaults/prometheus.yaml").as_bytes())?; 208 | } 209 | Ok(()) 210 | } 211 | -------------------------------------------------------------------------------- /plugin/velocity/src/main/kotlin/dev/njha/mycelium/plugin/velocity/Plugin.kt: -------------------------------------------------------------------------------- 1 | package dev.njha.mycelium.plugin.velocity 2 | 3 | import com.google.gson.Gson 4 | import com.google.inject.Inject 5 | import com.typesafe.config.ConfigFactory 6 | import com.velocitypowered.api.event.Subscribe 7 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent 8 | import com.velocitypowered.api.event.proxy.ProxyShutdownEvent 9 | import com.velocitypowered.api.plugin.Dependency 10 | import com.velocitypowered.api.plugin.Plugin 11 | import com.velocitypowered.api.plugin.annotation.DataDirectory 12 | import com.velocitypowered.api.proxy.ProxyServer 13 | import com.velocitypowered.api.proxy.server.ServerInfo 14 | import dev.cubxity.plugins.metrics.api.UnifiedMetrics 15 | import dev.cubxity.plugins.metrics.api.UnifiedMetricsProvider 16 | import dev.njha.mycelium.plugin.velocity.metrics.MetricsCollection 17 | import dev.njha.mycelium.plugin.velocity.metrics.MetricsCollector 18 | import dev.njha.mycelium.plugin.velocity.models.Server 19 | import io.ktor.application.* 20 | import io.ktor.client.* 21 | import io.ktor.client.engine.* 22 | import io.ktor.client.engine.java.* 23 | import io.ktor.client.request.* 24 | import io.ktor.client.statement.* 25 | import io.ktor.config.* 26 | import io.ktor.features.* 27 | import io.ktor.gson.* 28 | import io.ktor.http.* 29 | import io.ktor.request.* 30 | import io.ktor.response.* 31 | import io.ktor.routing.* 32 | import io.ktor.server.engine.* 33 | import io.ktor.server.netty.* 34 | import kotlinx.coroutines.* 35 | import org.slf4j.Logger 36 | import org.slf4j.LoggerFactory 37 | import java.net.ConnectException 38 | import java.net.InetSocketAddress 39 | import java.nio.file.Path 40 | import java.util.* 41 | import java.util.concurrent.TimeUnit 42 | import kotlin.collections.set 43 | import kotlin.reflect.full.declaredMemberFunctions 44 | import kotlin.reflect.jvm.isAccessible 45 | 46 | 47 | @Plugin( 48 | id = "mycelium", 49 | name = "Mycelium for Velocity", 50 | version = "0.4.0", 51 | dependencies = [Dependency(id = "unifiedmetrics", optional = false)], 52 | url = "https://nikhiljha.com/projects/mycelium", 53 | description = "syncs state with the Mycelium operator", 54 | authors = ["Nikhil Jha "] 55 | ) 56 | class Plugin { 57 | @Inject 58 | lateinit var log: Logger 59 | 60 | @Inject 61 | lateinit var proxy: ProxyServer 62 | 63 | private lateinit var metrics: MetricsCollector 64 | 65 | @Inject 66 | @DataDirectory 67 | lateinit var dataFolderPath: Path 68 | 69 | private suspend fun sync() { 70 | // TODO: Generate a TLS cert for the API server 71 | HttpClient(Java).use { httpClient -> 72 | var churn = 0 73 | val endpoint = System.getenv("MYCELIUM_ENDPOINT") ?: "localhost:8181" 74 | val namespace = System.getenv("K8S_NAMESPACE") ?: "default" 75 | val name = System.getenv("K8S_NAME") ?: "proxy" 76 | val url = "http://$endpoint/servers/$namespace/$name" 77 | try { 78 | // if no env set, assume development and attempt to connect to localhost 79 | val response = httpClient.get(url) { 80 | headers { 81 | append("Accept", "application/json") 82 | } 83 | } 84 | 85 | // parse servers 86 | val parsed = Gson().fromJson(response.readText(), Array::class.java) 87 | val newServers = HashMap() 88 | for (server in parsed) { 89 | newServers[server.name] = server 90 | } 91 | 92 | // remove servers 93 | for (oldServer in proxy.allServers) { 94 | if (!newServers.containsKey(oldServer.serverInfo.name)) { 95 | proxy.configuration.attemptConnectionOrder.remove(oldServer.serverInfo.name); 96 | proxy.unregisterServer(oldServer.serverInfo) 97 | log.info("removed server ${oldServer.serverInfo.name}") 98 | churn += 1 99 | } 100 | } 101 | 102 | val forcedHosts = mutableMapOf>(); 103 | val tryList: PriorityQueue = PriorityQueue(); 104 | 105 | // add servers 106 | for (server in newServers.values) { 107 | tryList.add(server) 108 | val rs = proxy.getServer(server.name) 109 | if (server.host != null) { 110 | if (forcedHosts.containsKey(server.host)) { 111 | forcedHosts[server.host]?.add(server.name) 112 | } else { 113 | forcedHosts[server.host] = mutableListOf(server.name) 114 | } 115 | } 116 | 117 | if (rs.isEmpty) { 118 | proxy.registerServer( 119 | ServerInfo( 120 | server.name, 121 | InetSocketAddress(server.address, 25565) 122 | ) 123 | ) 124 | log.info("added server ${server.name}") 125 | churn += 1 126 | } 127 | } 128 | 129 | // set default try list 130 | proxy.configuration.attemptConnectionOrder.clear() 131 | proxy.configuration.attemptConnectionOrder.addAll(tryList.map { server -> server.name }) 132 | 133 | // set forced hosts 134 | val forcedHostsField = proxy.configuration::class.java.getDeclaredField("forcedHosts") 135 | forcedHostsField.isAccessible = true 136 | val fhClass = forcedHostsField.get(proxy.configuration) 137 | fhClass::class.declaredMemberFunctions.find { it.name == "setForcedHosts" }?.let { 138 | it.isAccessible = true 139 | it.call(fhClass, forcedHosts) 140 | } 141 | 142 | // record metrics 143 | metrics.churn = churn 144 | } catch (e: ConnectException) { 145 | log.error("failed to connect to operator - could not sync server list! (url = $url)") 146 | } 147 | } 148 | } 149 | 150 | @Subscribe 151 | fun onStart(event: ProxyInitializeEvent) { 152 | // hook into metrics ews 153 | metrics = MetricsCollector() 154 | if (proxy.pluginManager.isLoaded("unifiedmetrics")) { 155 | val api: UnifiedMetrics = UnifiedMetricsProvider.get() 156 | api.metricsManager.registerCollection(MetricsCollection(metrics)) 157 | } 158 | 159 | // run mycelium api 160 | val ews = embeddedServer(Netty, environment = applicationEngineEnvironment { 161 | log = LoggerFactory.getLogger("mycelium") 162 | config = HoconApplicationConfig(ConfigFactory.load()) 163 | 164 | module { 165 | install(ContentNegotiation) { 166 | gson() 167 | } 168 | routing { 169 | get("/") { 170 | call.respondText("ok", ContentType.Text.Plain) 171 | } 172 | 173 | get("/debug/servers") { 174 | call.respond(proxy.allServers) 175 | } 176 | 177 | get("/debug/config") { 178 | call.respond(proxy.configuration) 179 | } 180 | } 181 | } 182 | 183 | connector { 184 | port = 9273 185 | host = "0.0.0.0" 186 | } 187 | }) 188 | ews.start(wait = false) 189 | 190 | // sync the servers from the operator now, and every 1 minute 191 | proxy.scheduler 192 | .buildTask(this) { runBlocking { launch { sync() } } } 193 | .repeat(1L, TimeUnit.MINUTES) 194 | .schedule() 195 | 196 | log.info("Hello, World.") 197 | } 198 | 199 | @Subscribe 200 | fun onStop(event: ProxyShutdownEvent) { 201 | log.info("Goodbye, World.") 202 | } 203 | } -------------------------------------------------------------------------------- /operator/src/objects/mod.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | array::IntoIter, 3 | collections::{BTreeMap, HashMap}, 4 | fmt::Debug, 5 | iter::Map, 6 | ops::Range, 7 | path::Path, 8 | sync::{Arc, RwLock}, 9 | time::Duration, 10 | }; 11 | 12 | use chrono::{DateTime, Utc}; 13 | use futures::{future::BoxFuture, FutureExt, StreamExt}; 14 | use k8s_openapi::{ 15 | api::{ 16 | apps::v1::{StatefulSet, StatefulSetSpec}, 17 | core::v1::{ 18 | ConfigMapVolumeSource, Container, EnvVar, PersistentVolumeClaim, PodSecurityContext, 19 | PodSpec, PodTemplateSpec, ResourceRequirements, SecurityContext, Service, ServicePort, 20 | ServiceSpec, Volume, VolumeMount, 21 | }, 22 | }, 23 | apimachinery::pkg::{ 24 | apis::meta::v1::{LabelSelector, ObjectMeta, OwnerReference}, 25 | util::intstr::IntOrString, 26 | }, 27 | }; 28 | use k8s_openapi::api::apps::v1::{Deployment, DeploymentSpec}; 29 | use k8s_openapi::api::core::v1::{EnvVarSource, Secret, SecretKeySelector}; 30 | use k8s_openapi::api::policy::v1::{PodDisruptionBudget, PodDisruptionBudgetSpec}; 31 | use kube::{ 32 | api::{ListParams, Patch, PatchParams}, 33 | Api, Client, Resource, ResourceExt, 34 | }; 35 | use kube_runtime::{ 36 | controller::{Context, ReconcilerAction}, 37 | Controller, 38 | }; 39 | use prometheus::{ 40 | default_registry, proto::MetricFamily, register_histogram_vec, register_int_counter, 41 | HistogramOpts, HistogramVec, IntCounter, 42 | }; 43 | use schemars::JsonSchema; 44 | use serde::{Deserialize, Serialize}; 45 | use tracing::{debug, error, event, field, info, instrument, trace, warn, Level, Span}; 46 | use sha2::{Sha224, Digest}; 47 | 48 | use crate::{ 49 | helpers::{manager::Data, metrics::Metrics, state::State}, 50 | objects::minecraft_set::MinecraftSetSpec, 51 | Error, MinecraftProxy, MinecraftSet, 52 | }; 53 | use crate::Error::MyceliumError; 54 | use crate::helpers::jarapi::get_download_url; 55 | 56 | pub mod minecraft_proxy; 57 | pub mod minecraft_set; 58 | 59 | #[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, JsonSchema)] 60 | pub struct ConfigOptions { 61 | /// name of configmap to mount 62 | pub name: String, 63 | 64 | /// location relative to the Minecraft root to mount the configmap 65 | pub path: String, 66 | } 67 | 68 | #[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, JsonSchema)] 69 | #[serde(rename_all = "camelCase")] 70 | pub struct ContainerOptions { 71 | /// should the container be stateful? (default = true) 72 | pub stateful: Option, 73 | 74 | /// resource requirements for the java pod 75 | pub resources: Option, 76 | 77 | /// volume to mount to the minecraft root (only useful for replicas = 1) 78 | pub volume: Option, 79 | 80 | /// volume claim template to use for the minecraft root (overrides the volume field if set) 81 | pub volume_claim_template: Option, 82 | 83 | /// nodes that the java pod can be scheduled on 84 | pub node_selector: Option>, 85 | 86 | /// pod security context for the minecraft server (should be restrictive) 87 | pub security_context: Option, 88 | } 89 | 90 | #[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, JsonSchema)] 91 | pub struct RunnerOptions { 92 | /// server jar to download and run 93 | pub jar: VersionTriple, 94 | 95 | /// space separated options to pass to the JVM (i.e. -Dsomething=something -Dother=other) 96 | pub jvm: Option, 97 | 98 | /// configmaps to mount inside the minecraft root 99 | pub config: Option>, 100 | 101 | /// list of plugin URLs to download on server start 102 | pub plugins: Option>, 103 | } 104 | 105 | #[derive(Serialize, Deserialize, Default, Debug, PartialEq, Clone, JsonSchema)] 106 | pub struct VersionTriple { 107 | /// type of jar (currently only `paper` or `velocity` is supported) 108 | pub r#type: String, 109 | 110 | /// version according to the PaperMC API 111 | pub version: String, 112 | 113 | /// build according to the PaperMC API 114 | pub build: String, 115 | } 116 | 117 | pub fn make_volume_mount(co: &ConfigOptions) -> VolumeMount { 118 | return VolumeMount { 119 | name: co.name.clone(), 120 | mount_path: String::from( 121 | Path::new("/config/") 122 | .join(&co.path) 123 | .to_str() 124 | .expect("mount path"), 125 | ), 126 | ..VolumeMount::default() 127 | }; 128 | } 129 | 130 | pub fn make_volume(co: &ConfigOptions) -> Volume { 131 | Volume { 132 | name: co.name.clone(), 133 | config_map: Some(ConfigMapVolumeSource { 134 | name: Some(co.name.clone()), 135 | ..ConfigMapVolumeSource::default() 136 | }), 137 | ..Volume::default() 138 | } 139 | } 140 | 141 | pub fn object_to_owner_reference>( 142 | meta: ObjectMeta, 143 | ) -> Result { 144 | Ok(OwnerReference { 145 | api_version: K::api_version(&()).to_string(), 146 | kind: K::kind(&()).to_string(), 147 | name: meta.name.ok_or_else(|| MyceliumError("failed to get name".into()))?, 148 | uid: meta.uid.ok_or_else(|| MyceliumError("failed to get uid".into()))?, 149 | ..OwnerReference::default() 150 | }) 151 | } 152 | 153 | pub async fn generic_reconcile>( 154 | env: Vec, 155 | port: IntOrString, 156 | ctx: Context, 157 | shortname: String, 158 | crd: T, 159 | container: ContainerOptions, 160 | runner: RunnerOptions, 161 | replicas: i32, 162 | ) -> Result<(), Error> { 163 | let name = ResourceExt::name(&crd); 164 | let ns = ResourceExt::namespace(&crd) 165 | .ok_or_else(|| MyceliumError("failed to get namespace".into()))?; 166 | 167 | let owner_reference = OwnerReference { 168 | controller: Some(true), 169 | ..object_to_owner_reference::(crd.meta().clone())? 170 | }; 171 | 172 | let client = ctx.get_ref().client.clone(); 173 | // Note: This will only error with PoisonError, which is unrecoverable and so we 174 | // should panic. 175 | ctx.get_ref().state.write().expect("last_event").last_event = Utc::now(); 176 | 177 | let labels = BTreeMap::from_iter(IntoIter::new([( 178 | format!("mycelium.njha.dev/{}", shortname), 179 | name.clone(), 180 | )])); 181 | let configs = runner.config.unwrap_or_default(); 182 | let mut volume_mounts: Vec = configs.iter().map(make_volume_mount).collect(); 183 | let mut volumes: Vec = configs.iter().map(make_volume).collect(); 184 | let mut tpl_volume: Vec = vec![]; 185 | 186 | if let Some(volume_tpl) = container.volume_claim_template { 187 | volume_mounts.push(VolumeMount { 188 | mount_path: "/data".to_string(), 189 | name: volume_tpl.metadata.clone().name 190 | .ok_or_else(|| MyceliumError("volumeClaimTemplate name".into()))?, 191 | ..VolumeMount::default() 192 | }); 193 | tpl_volume.push(volume_tpl); 194 | } else if let Some(volume) = container.volume { 195 | let name = volume.name.clone(); 196 | volumes.push(volume); 197 | volume_mounts.push(VolumeMount { 198 | mount_path: "/data".to_string(), 199 | name, 200 | ..VolumeMount::default() 201 | }); 202 | } 203 | 204 | let env: Vec = vec![ 205 | EnvVar { 206 | name: String::from("MYCELIUM_JVM_OPTS"), 207 | value: runner.jvm, 208 | value_from: None, 209 | }, 210 | EnvVar { 211 | name: String::from("MYCELIUM_FW_TOKEN"), 212 | value: None, 213 | value_from: Some(EnvVarSource { 214 | secret_key_ref: Some(SecretKeySelector { 215 | key: "forwarding_token".to_string(), 216 | name: Some(name.clone()), 217 | optional: Some(false) 218 | }), 219 | ..EnvVarSource::default() 220 | }), 221 | }, 222 | EnvVar { 223 | name: String::from("MYCELIUM_RUNNER_JAR_URL"), 224 | value: Some(get_download_url( 225 | &runner.jar.r#type, 226 | &runner.jar.version, 227 | &runner.jar.build, 228 | )), 229 | value_from: None, 230 | }, 231 | ].into_iter().chain(env).collect(); 232 | let statefulset = StatefulSet { 233 | metadata: ObjectMeta { 234 | name: Some(name.clone()), 235 | owner_references: Some(vec![owner_reference.clone()]), 236 | ..ObjectMeta::default() 237 | }, 238 | spec: Some(StatefulSetSpec { 239 | selector: LabelSelector { 240 | match_labels: Some(labels.clone()), 241 | ..LabelSelector::default() 242 | }, 243 | service_name: name.clone(), 244 | replicas: Some(replicas), 245 | template: PodTemplateSpec { 246 | metadata: Some(ObjectMeta { 247 | labels: Some(labels.clone()), 248 | annotations: Some(vec![("prometheus.io/port".into(), "9970".into()), 249 | ("prometheus.io/scrape".into(), "true".into())] 250 | .into_iter().collect()), 251 | ..ObjectMeta::default() 252 | }), 253 | spec: Some(PodSpec { 254 | security_context: container.security_context, 255 | containers: vec![Container { 256 | name: name.clone(), 257 | tty: Some(true), 258 | stdin: Some(true), 259 | image: Some(String::from(&ctx.get_ref().config.runner_image)), 260 | image_pull_policy: Some(String::from("IfNotPresent")), 261 | resources: container.resources, 262 | env: Some(env), 263 | volume_mounts: Some(volume_mounts), 264 | ..Container::default() 265 | }], 266 | volumes: Some(volumes), 267 | ..PodSpec::default() 268 | }), 269 | }, 270 | volume_claim_templates: Some(tpl_volume), 271 | ..StatefulSetSpec::default() 272 | }), 273 | status: None, 274 | }; 275 | 276 | let pdb = PodDisruptionBudget { 277 | metadata: ObjectMeta { 278 | name: Some(name.clone()), 279 | owner_references: Some(vec![owner_reference.clone()]), 280 | ..ObjectMeta::default() 281 | }, 282 | spec: Some(PodDisruptionBudgetSpec { 283 | max_unavailable: Some(IntOrString::Int(0)), 284 | min_available: None, 285 | selector: Some(LabelSelector { 286 | match_expressions: None, 287 | match_labels: Some(labels 288 | .iter() 289 | .chain(vec![("mycelium.njha.dev/destroyable".to_string(), "false".to_string())]) 290 | .collect() 291 | ), 292 | }), 293 | }), 294 | ..PodDisruptionBudget::default() 295 | }; 296 | 297 | let service = Service { 298 | metadata: ObjectMeta { 299 | name: Some(name.clone()), 300 | owner_references: Some(vec![owner_reference.clone()]), 301 | ..ObjectMeta::default() 302 | }, 303 | spec: Some(ServiceSpec { 304 | // https://kubernetes.io/docs/concepts/services-networking/service/#headless-services 305 | cluster_ip: Some(String::from("None")), 306 | selector: Some(labels), 307 | ports: Some(vec![ServicePort { 308 | protocol: Some(String::from("TCP")), 309 | port: 25565, 310 | target_port: Some(port), 311 | ..ServicePort::default() 312 | }]), 313 | ..ServiceSpec::default() 314 | }), 315 | status: None, 316 | }; 317 | 318 | let mut token = sha2::Sha224::new(); 319 | token.update(format!("{}{}", ctx.get_ref().config.forwarding_secret, ns.clone()).as_bytes()); 320 | let token = base64::encode(token.finalize()); 321 | let secret = Secret { 322 | metadata: ObjectMeta { 323 | name: Some(name.clone()), 324 | owner_references: Some(vec![owner_reference]), 325 | ..ObjectMeta::default() 326 | }, 327 | string_data: Some(vec![("forwarding_token".into(), token)] 328 | .into_iter().collect()), 329 | ..Secret::default() 330 | }; 331 | 332 | kube::Api::::namespaced(client.clone(), &ns) 333 | .patch( 334 | &name, 335 | &PatchParams::apply("mycelium.njha.dev"), 336 | &Patch::Apply(&pdb), 337 | ).await?; 338 | 339 | kube::Api::::namespaced(client.clone(), &ns) 340 | .patch( 341 | &name, 342 | &PatchParams::apply("mycelium.njha.dev"), 343 | &Patch::Apply(&statefulset), 344 | ) 345 | .await?; 346 | 347 | kube::Api::::namespaced(client.clone(), &ns) 348 | .patch( 349 | &name, 350 | &PatchParams::apply("mycelium.njha.dev"), 351 | &Patch::Apply(&service), 352 | ) 353 | .await?; 354 | 355 | kube::Api::::namespaced(client.clone(), &ns) 356 | .patch( 357 | &name, 358 | &PatchParams::apply("mycelium.njha.dev"), 359 | &Patch::Apply(&secret), 360 | ) 361 | .await?; 362 | 363 | Ok(()) 364 | } 365 | -------------------------------------------------------------------------------- /operator/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "actix-codec" 7 | version = "0.4.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "13895df506faee81e423febbae3a33b27fca71831b96bb3d60adf16ebcfea952" 10 | dependencies = [ 11 | "bitflags", 12 | "bytes", 13 | "futures-core", 14 | "futures-sink", 15 | "log", 16 | "memchr", 17 | "pin-project-lite", 18 | "tokio", 19 | "tokio-util", 20 | ] 21 | 22 | [[package]] 23 | name = "actix-http" 24 | version = "3.0.0-beta.16" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "6294c508c1413346857838356f53f45dbfd257ea31dca19470d9ce78750a7d37" 27 | dependencies = [ 28 | "actix-codec", 29 | "actix-rt", 30 | "actix-service", 31 | "actix-utils", 32 | "ahash", 33 | "base64", 34 | "bitflags", 35 | "brotli2", 36 | "bytes", 37 | "bytestring", 38 | "derive_more", 39 | "encoding_rs", 40 | "flate2", 41 | "futures-core", 42 | "futures-task", 43 | "h2", 44 | "http", 45 | "httparse", 46 | "httpdate", 47 | "itoa 0.4.7", 48 | "language-tags", 49 | "local-channel", 50 | "log", 51 | "mime", 52 | "percent-encoding", 53 | "pin-project-lite", 54 | "rand", 55 | "sha-1", 56 | "smallvec", 57 | "zstd", 58 | ] 59 | 60 | [[package]] 61 | name = "actix-macros" 62 | version = "0.2.3" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" 65 | dependencies = [ 66 | "quote", 67 | "syn", 68 | ] 69 | 70 | [[package]] 71 | name = "actix-router" 72 | version = "0.5.0-beta.3" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "ddd9f117b910fbcce6e9f45092ffd4ff017785a346d09e2d4fd049f4e20384f4" 75 | dependencies = [ 76 | "bytestring", 77 | "firestorm", 78 | "http", 79 | "log", 80 | "regex", 81 | "serde", 82 | ] 83 | 84 | [[package]] 85 | name = "actix-rt" 86 | version = "2.5.0" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "05c2f80ce8d0c990941c7a7a931f69fd0701b76d521f8d36298edf59cd3fbf1f" 89 | dependencies = [ 90 | "actix-macros", 91 | "futures-core", 92 | "tokio", 93 | ] 94 | 95 | [[package]] 96 | name = "actix-server" 97 | version = "2.0.0-rc.1" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "78c9b22794b8af1c2e02434873ef858f2a7db40dbbf861ce77a04cd81ac6b767" 100 | dependencies = [ 101 | "actix-rt", 102 | "actix-service", 103 | "actix-utils", 104 | "futures-core", 105 | "futures-util", 106 | "log", 107 | "mio 0.8.0", 108 | "num_cpus", 109 | "socket2", 110 | "tokio", 111 | ] 112 | 113 | [[package]] 114 | name = "actix-service" 115 | version = "2.0.0" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "77f5f9d66a8730d0fae62c26f3424f5751e5518086628a40b7ab6fca4a705034" 118 | dependencies = [ 119 | "futures-core", 120 | "paste", 121 | "pin-project-lite", 122 | ] 123 | 124 | [[package]] 125 | name = "actix-utils" 126 | version = "3.0.0" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "e491cbaac2e7fc788dfff99ff48ef317e23b3cf63dbaf7aaab6418f40f92aa94" 129 | dependencies = [ 130 | "local-waker", 131 | "pin-project-lite", 132 | ] 133 | 134 | [[package]] 135 | name = "actix-web" 136 | version = "4.0.0-beta.15" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "4609cf57246040316642d4dc4c03d7f3d4a083a892122829dbd9e6ec8db7cd67" 139 | dependencies = [ 140 | "actix-codec", 141 | "actix-http", 142 | "actix-macros", 143 | "actix-router", 144 | "actix-rt", 145 | "actix-server", 146 | "actix-service", 147 | "actix-utils", 148 | "actix-web-codegen", 149 | "ahash", 150 | "bytes", 151 | "cfg-if", 152 | "cookie", 153 | "derive_more", 154 | "encoding_rs", 155 | "futures-core", 156 | "futures-util", 157 | "itoa 0.4.7", 158 | "language-tags", 159 | "log", 160 | "mime", 161 | "once_cell", 162 | "paste", 163 | "pin-project-lite", 164 | "regex", 165 | "serde", 166 | "serde_json", 167 | "serde_urlencoded", 168 | "smallvec", 169 | "socket2", 170 | "time 0.3.5", 171 | "url", 172 | ] 173 | 174 | [[package]] 175 | name = "actix-web-codegen" 176 | version = "0.5.0-beta.6" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "30a90b7f6c2fde9a1fe3df4da758c2c3c9d620dfa3eae4da0b6925dc0a13444a" 179 | dependencies = [ 180 | "actix-router", 181 | "proc-macro2", 182 | "quote", 183 | "syn", 184 | ] 185 | 186 | [[package]] 187 | name = "adler" 188 | version = "1.0.2" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 191 | 192 | [[package]] 193 | name = "ahash" 194 | version = "0.7.4" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" 197 | dependencies = [ 198 | "getrandom", 199 | "once_cell", 200 | "version_check", 201 | ] 202 | 203 | [[package]] 204 | name = "aho-corasick" 205 | version = "0.7.18" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 208 | dependencies = [ 209 | "memchr", 210 | ] 211 | 212 | [[package]] 213 | name = "ansi_term" 214 | version = "0.12.1" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 217 | dependencies = [ 218 | "winapi", 219 | ] 220 | 221 | [[package]] 222 | name = "anyhow" 223 | version = "1.0.42" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" 226 | 227 | [[package]] 228 | name = "async-stream" 229 | version = "0.3.2" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" 232 | dependencies = [ 233 | "async-stream-impl", 234 | "futures-core", 235 | ] 236 | 237 | [[package]] 238 | name = "async-stream-impl" 239 | version = "0.3.2" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" 242 | dependencies = [ 243 | "proc-macro2", 244 | "quote", 245 | "syn", 246 | ] 247 | 248 | [[package]] 249 | name = "async-trait" 250 | version = "0.1.50" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" 253 | dependencies = [ 254 | "proc-macro2", 255 | "quote", 256 | "syn", 257 | ] 258 | 259 | [[package]] 260 | name = "autocfg" 261 | version = "1.0.1" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 264 | 265 | [[package]] 266 | name = "base-x" 267 | version = "0.2.8" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" 270 | 271 | [[package]] 272 | name = "base64" 273 | version = "0.13.0" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 276 | 277 | [[package]] 278 | name = "bitflags" 279 | version = "1.2.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 282 | 283 | [[package]] 284 | name = "block-buffer" 285 | version = "0.9.0" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 288 | dependencies = [ 289 | "generic-array", 290 | ] 291 | 292 | [[package]] 293 | name = "block-buffer" 294 | version = "0.10.0" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" 297 | dependencies = [ 298 | "generic-array", 299 | ] 300 | 301 | [[package]] 302 | name = "brotli-sys" 303 | version = "0.3.2" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" 306 | dependencies = [ 307 | "cc", 308 | "libc", 309 | ] 310 | 311 | [[package]] 312 | name = "brotli2" 313 | version = "0.3.2" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" 316 | dependencies = [ 317 | "brotli-sys", 318 | "libc", 319 | ] 320 | 321 | [[package]] 322 | name = "bumpalo" 323 | version = "3.7.0" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" 326 | 327 | [[package]] 328 | name = "bytes" 329 | version = "1.1.0" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 332 | 333 | [[package]] 334 | name = "bytestring" 335 | version = "1.0.0" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "90706ba19e97b90786e19dc0d5e2abd80008d99d4c0c5d1ad0b5e72cec7c494d" 338 | dependencies = [ 339 | "bytes", 340 | ] 341 | 342 | [[package]] 343 | name = "cc" 344 | version = "1.0.68" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" 347 | dependencies = [ 348 | "jobserver", 349 | ] 350 | 351 | [[package]] 352 | name = "cfg-if" 353 | version = "1.0.0" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 356 | 357 | [[package]] 358 | name = "chrono" 359 | version = "0.4.19" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 362 | dependencies = [ 363 | "libc", 364 | "num-integer", 365 | "num-traits", 366 | "serde", 367 | "time 0.1.44", 368 | "winapi", 369 | ] 370 | 371 | [[package]] 372 | name = "combine" 373 | version = "4.6.2" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "b2b2f5d0ee456f3928812dfc8c6d9a1d592b98678f6d56db9b0cd2b7bc6c8db5" 376 | dependencies = [ 377 | "bytes", 378 | "memchr", 379 | ] 380 | 381 | [[package]] 382 | name = "const_fn" 383 | version = "0.4.8" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7" 386 | 387 | [[package]] 388 | name = "convert_case" 389 | version = "0.4.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 392 | 393 | [[package]] 394 | name = "cookie" 395 | version = "0.15.0" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "ffdf8865bac3d9a3bde5bde9088ca431b11f5d37c7a578b8086af77248b76627" 398 | dependencies = [ 399 | "percent-encoding", 400 | "time 0.2.27", 401 | "version_check", 402 | ] 403 | 404 | [[package]] 405 | name = "core-foundation" 406 | version = "0.9.1" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" 409 | dependencies = [ 410 | "core-foundation-sys", 411 | "libc", 412 | ] 413 | 414 | [[package]] 415 | name = "core-foundation-sys" 416 | version = "0.8.2" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" 419 | 420 | [[package]] 421 | name = "cpufeatures" 422 | version = "0.1.5" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" 425 | dependencies = [ 426 | "libc", 427 | ] 428 | 429 | [[package]] 430 | name = "cpufeatures" 431 | version = "0.2.1" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" 434 | dependencies = [ 435 | "libc", 436 | ] 437 | 438 | [[package]] 439 | name = "crc32fast" 440 | version = "1.2.1" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 443 | dependencies = [ 444 | "cfg-if", 445 | ] 446 | 447 | [[package]] 448 | name = "crypto-common" 449 | version = "0.1.1" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" 452 | dependencies = [ 453 | "generic-array", 454 | ] 455 | 456 | [[package]] 457 | name = "darling" 458 | version = "0.13.1" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" 461 | dependencies = [ 462 | "darling_core", 463 | "darling_macro", 464 | ] 465 | 466 | [[package]] 467 | name = "darling_core" 468 | version = "0.13.1" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" 471 | dependencies = [ 472 | "fnv", 473 | "ident_case", 474 | "proc-macro2", 475 | "quote", 476 | "strsim", 477 | "syn", 478 | ] 479 | 480 | [[package]] 481 | name = "darling_macro" 482 | version = "0.13.1" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" 485 | dependencies = [ 486 | "darling_core", 487 | "quote", 488 | "syn", 489 | ] 490 | 491 | [[package]] 492 | name = "dashmap" 493 | version = "4.0.2" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" 496 | dependencies = [ 497 | "cfg-if", 498 | "num_cpus", 499 | ] 500 | 501 | [[package]] 502 | name = "derivative" 503 | version = "2.2.0" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 506 | dependencies = [ 507 | "proc-macro2", 508 | "quote", 509 | "syn", 510 | ] 511 | 512 | [[package]] 513 | name = "derive_more" 514 | version = "0.99.16" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df" 517 | dependencies = [ 518 | "convert_case", 519 | "proc-macro2", 520 | "quote", 521 | "rustc_version 0.3.3", 522 | "syn", 523 | ] 524 | 525 | [[package]] 526 | name = "digest" 527 | version = "0.9.0" 528 | source = "registry+https://github.com/rust-lang/crates.io-index" 529 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 530 | dependencies = [ 531 | "generic-array", 532 | ] 533 | 534 | [[package]] 535 | name = "digest" 536 | version = "0.10.1" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" 539 | dependencies = [ 540 | "block-buffer 0.10.0", 541 | "crypto-common", 542 | "generic-array", 543 | ] 544 | 545 | [[package]] 546 | name = "dirs-next" 547 | version = "2.0.0" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 550 | dependencies = [ 551 | "cfg-if", 552 | "dirs-sys-next", 553 | ] 554 | 555 | [[package]] 556 | name = "dirs-sys-next" 557 | version = "0.1.2" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 560 | dependencies = [ 561 | "libc", 562 | "redox_users", 563 | "winapi", 564 | ] 565 | 566 | [[package]] 567 | name = "discard" 568 | version = "1.0.4" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 571 | 572 | [[package]] 573 | name = "dyn-clone" 574 | version = "1.0.4" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" 577 | 578 | [[package]] 579 | name = "either" 580 | version = "1.6.1" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 583 | 584 | [[package]] 585 | name = "encoding_rs" 586 | version = "0.8.28" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" 589 | dependencies = [ 590 | "cfg-if", 591 | ] 592 | 593 | [[package]] 594 | name = "firestorm" 595 | version = "0.4.6" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "31586bda1b136406162e381a3185a506cdfc1631708dd40cba2f6628d8634499" 598 | 599 | [[package]] 600 | name = "fixedbitset" 601 | version = "0.2.0" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" 604 | 605 | [[package]] 606 | name = "flate2" 607 | version = "1.0.20" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" 610 | dependencies = [ 611 | "cfg-if", 612 | "crc32fast", 613 | "libc", 614 | "miniz_oxide", 615 | ] 616 | 617 | [[package]] 618 | name = "fnv" 619 | version = "1.0.7" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 622 | 623 | [[package]] 624 | name = "foreign-types" 625 | version = "0.3.2" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 628 | dependencies = [ 629 | "foreign-types-shared", 630 | ] 631 | 632 | [[package]] 633 | name = "foreign-types-shared" 634 | version = "0.1.1" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 637 | 638 | [[package]] 639 | name = "form_urlencoded" 640 | version = "1.0.1" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 643 | dependencies = [ 644 | "matches", 645 | "percent-encoding", 646 | ] 647 | 648 | [[package]] 649 | name = "futures" 650 | version = "0.3.19" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" 653 | dependencies = [ 654 | "futures-channel", 655 | "futures-core", 656 | "futures-executor", 657 | "futures-io", 658 | "futures-sink", 659 | "futures-task", 660 | "futures-util", 661 | ] 662 | 663 | [[package]] 664 | name = "futures-channel" 665 | version = "0.3.19" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" 668 | dependencies = [ 669 | "futures-core", 670 | "futures-sink", 671 | ] 672 | 673 | [[package]] 674 | name = "futures-core" 675 | version = "0.3.19" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" 678 | 679 | [[package]] 680 | name = "futures-executor" 681 | version = "0.3.19" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" 684 | dependencies = [ 685 | "futures-core", 686 | "futures-task", 687 | "futures-util", 688 | ] 689 | 690 | [[package]] 691 | name = "futures-io" 692 | version = "0.3.19" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" 695 | 696 | [[package]] 697 | name = "futures-macro" 698 | version = "0.3.19" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" 701 | dependencies = [ 702 | "proc-macro2", 703 | "quote", 704 | "syn", 705 | ] 706 | 707 | [[package]] 708 | name = "futures-sink" 709 | version = "0.3.19" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" 712 | 713 | [[package]] 714 | name = "futures-task" 715 | version = "0.3.19" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" 718 | 719 | [[package]] 720 | name = "futures-util" 721 | version = "0.3.19" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" 724 | dependencies = [ 725 | "futures-channel", 726 | "futures-core", 727 | "futures-io", 728 | "futures-macro", 729 | "futures-sink", 730 | "futures-task", 731 | "memchr", 732 | "pin-project-lite", 733 | "pin-utils", 734 | "slab", 735 | ] 736 | 737 | [[package]] 738 | name = "generic-array" 739 | version = "0.14.4" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 742 | dependencies = [ 743 | "typenum", 744 | "version_check", 745 | ] 746 | 747 | [[package]] 748 | name = "getrandom" 749 | version = "0.2.3" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 752 | dependencies = [ 753 | "cfg-if", 754 | "libc", 755 | "wasi", 756 | ] 757 | 758 | [[package]] 759 | name = "h2" 760 | version = "0.3.9" 761 | source = "registry+https://github.com/rust-lang/crates.io-index" 762 | checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" 763 | dependencies = [ 764 | "bytes", 765 | "fnv", 766 | "futures-core", 767 | "futures-sink", 768 | "futures-util", 769 | "http", 770 | "indexmap", 771 | "slab", 772 | "tokio", 773 | "tokio-util", 774 | "tracing", 775 | ] 776 | 777 | [[package]] 778 | name = "hashbrown" 779 | version = "0.11.2" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 782 | 783 | [[package]] 784 | name = "heck" 785 | version = "0.3.3" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" 788 | dependencies = [ 789 | "unicode-segmentation", 790 | ] 791 | 792 | [[package]] 793 | name = "hermit-abi" 794 | version = "0.1.19" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 797 | dependencies = [ 798 | "libc", 799 | ] 800 | 801 | [[package]] 802 | name = "http" 803 | version = "0.2.5" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" 806 | dependencies = [ 807 | "bytes", 808 | "fnv", 809 | "itoa 0.4.7", 810 | ] 811 | 812 | [[package]] 813 | name = "http-body" 814 | version = "0.4.2" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" 817 | dependencies = [ 818 | "bytes", 819 | "http", 820 | "pin-project-lite", 821 | ] 822 | 823 | [[package]] 824 | name = "http-range-header" 825 | version = "0.3.0" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" 828 | 829 | [[package]] 830 | name = "httparse" 831 | version = "1.5.1" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" 834 | 835 | [[package]] 836 | name = "httpdate" 837 | version = "1.0.1" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" 840 | 841 | [[package]] 842 | name = "hyper" 843 | version = "0.14.16" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" 846 | dependencies = [ 847 | "bytes", 848 | "futures-channel", 849 | "futures-core", 850 | "futures-util", 851 | "h2", 852 | "http", 853 | "http-body", 854 | "httparse", 855 | "httpdate", 856 | "itoa 0.4.7", 857 | "pin-project-lite", 858 | "socket2", 859 | "tokio", 860 | "tower-service", 861 | "tracing", 862 | "want", 863 | ] 864 | 865 | [[package]] 866 | name = "hyper-timeout" 867 | version = "0.4.1" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" 870 | dependencies = [ 871 | "hyper", 872 | "pin-project-lite", 873 | "tokio", 874 | "tokio-io-timeout", 875 | ] 876 | 877 | [[package]] 878 | name = "hyper-tls" 879 | version = "0.5.0" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 882 | dependencies = [ 883 | "bytes", 884 | "hyper", 885 | "native-tls", 886 | "tokio", 887 | "tokio-native-tls", 888 | ] 889 | 890 | [[package]] 891 | name = "ident_case" 892 | version = "1.0.1" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 895 | 896 | [[package]] 897 | name = "idna" 898 | version = "0.2.3" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 901 | dependencies = [ 902 | "matches", 903 | "unicode-bidi", 904 | "unicode-normalization", 905 | ] 906 | 907 | [[package]] 908 | name = "indexmap" 909 | version = "1.7.0" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" 912 | dependencies = [ 913 | "autocfg", 914 | "hashbrown", 915 | ] 916 | 917 | [[package]] 918 | name = "instant" 919 | version = "0.1.10" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" 922 | dependencies = [ 923 | "cfg-if", 924 | ] 925 | 926 | [[package]] 927 | name = "ipnet" 928 | version = "2.3.1" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" 931 | 932 | [[package]] 933 | name = "itertools" 934 | version = "0.9.0" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" 937 | dependencies = [ 938 | "either", 939 | ] 940 | 941 | [[package]] 942 | name = "itertools" 943 | version = "0.10.3" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" 946 | dependencies = [ 947 | "either", 948 | ] 949 | 950 | [[package]] 951 | name = "itoa" 952 | version = "0.4.7" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 955 | 956 | [[package]] 957 | name = "itoa" 958 | version = "1.0.1" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" 961 | 962 | [[package]] 963 | name = "jobserver" 964 | version = "0.1.22" 965 | source = "registry+https://github.com/rust-lang/crates.io-index" 966 | checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" 967 | dependencies = [ 968 | "libc", 969 | ] 970 | 971 | [[package]] 972 | name = "js-sys" 973 | version = "0.3.51" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" 976 | dependencies = [ 977 | "wasm-bindgen", 978 | ] 979 | 980 | [[package]] 981 | name = "json-patch" 982 | version = "0.2.6" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "f995a3c8f2bc3dd52a18a583e90f9ec109c047fa1603a853e46bcda14d2e279d" 985 | dependencies = [ 986 | "serde", 987 | "serde_json", 988 | "treediff", 989 | ] 990 | 991 | [[package]] 992 | name = "jsonpath_lib" 993 | version = "0.3.0" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" 996 | dependencies = [ 997 | "log", 998 | "serde", 999 | "serde_json", 1000 | ] 1001 | 1002 | [[package]] 1003 | name = "k8s-openapi" 1004 | version = "0.13.1" 1005 | source = "registry+https://github.com/rust-lang/crates.io-index" 1006 | checksum = "4f8de9873b904e74b3533f77493731ee26742418077503683db44e1b3c54aa5c" 1007 | dependencies = [ 1008 | "base64", 1009 | "bytes", 1010 | "chrono", 1011 | "schemars", 1012 | "serde", 1013 | "serde-value", 1014 | "serde_json", 1015 | ] 1016 | 1017 | [[package]] 1018 | name = "kstring" 1019 | version = "1.0.6" 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" 1021 | checksum = "8b310ccceade8121d7d77fee406160e457c2f4e7c7982d589da3499bc7ea4526" 1022 | dependencies = [ 1023 | "serde", 1024 | ] 1025 | 1026 | [[package]] 1027 | name = "kube" 1028 | version = "0.65.0" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "9ec231e9ec9e84789f9eb414d1ac40ce6c90d0517fb272a335b4233f2e272b1e" 1031 | dependencies = [ 1032 | "k8s-openapi", 1033 | "kube-client", 1034 | "kube-core", 1035 | "kube-derive", 1036 | ] 1037 | 1038 | [[package]] 1039 | name = "kube-client" 1040 | version = "0.65.0" 1041 | source = "registry+https://github.com/rust-lang/crates.io-index" 1042 | checksum = "95dddb1fcced906d79cdae530ff39079c2d3772b2d623088fdbebe610bfa8217" 1043 | dependencies = [ 1044 | "base64", 1045 | "bytes", 1046 | "chrono", 1047 | "dirs-next", 1048 | "either", 1049 | "futures", 1050 | "http", 1051 | "http-body", 1052 | "hyper", 1053 | "hyper-timeout", 1054 | "hyper-tls", 1055 | "jsonpath_lib", 1056 | "k8s-openapi", 1057 | "kube-core", 1058 | "openssl", 1059 | "pem", 1060 | "pin-project", 1061 | "serde", 1062 | "serde_json", 1063 | "serde_yaml", 1064 | "thiserror", 1065 | "tokio", 1066 | "tokio-native-tls", 1067 | "tokio-util", 1068 | "tower", 1069 | "tower-http", 1070 | "tracing", 1071 | ] 1072 | 1073 | [[package]] 1074 | name = "kube-core" 1075 | version = "0.65.0" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "c52b6ab05d160691083430f6f431707a4e05b64903f2ffa0095ee5efde759117" 1078 | dependencies = [ 1079 | "chrono", 1080 | "form_urlencoded", 1081 | "http", 1082 | "json-patch", 1083 | "k8s-openapi", 1084 | "once_cell", 1085 | "serde", 1086 | "serde_json", 1087 | "thiserror", 1088 | ] 1089 | 1090 | [[package]] 1091 | name = "kube-derive" 1092 | version = "0.65.0" 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" 1094 | checksum = "b98ff3d647085c6c025083efad0435890867f4bea042fc62d408ab3aeb1cdf66" 1095 | dependencies = [ 1096 | "darling", 1097 | "proc-macro2", 1098 | "quote", 1099 | "serde_json", 1100 | "syn", 1101 | ] 1102 | 1103 | [[package]] 1104 | name = "kube-runtime" 1105 | version = "0.65.0" 1106 | source = "registry+https://github.com/rust-lang/crates.io-index" 1107 | checksum = "406280d56304bc79b37af7f78e0d9719a4eebc3f46e5e79663154874b7696a48" 1108 | dependencies = [ 1109 | "dashmap", 1110 | "derivative", 1111 | "futures", 1112 | "json-patch", 1113 | "k8s-openapi", 1114 | "kube-client", 1115 | "pin-project", 1116 | "serde", 1117 | "serde_json", 1118 | "smallvec", 1119 | "thiserror", 1120 | "tokio", 1121 | "tokio-util", 1122 | "tracing", 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "language-tags" 1127 | version = "0.3.2" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 1130 | 1131 | [[package]] 1132 | name = "lazy_static" 1133 | version = "1.4.0" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1136 | 1137 | [[package]] 1138 | name = "libc" 1139 | version = "0.2.112" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" 1142 | 1143 | [[package]] 1144 | name = "linked-hash-map" 1145 | version = "0.5.4" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" 1148 | 1149 | [[package]] 1150 | name = "local-channel" 1151 | version = "0.1.2" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "6246c68cf195087205a0512559c97e15eaf95198bf0e206d662092cdcb03fe9f" 1154 | dependencies = [ 1155 | "futures-core", 1156 | "futures-sink", 1157 | "futures-util", 1158 | "local-waker", 1159 | ] 1160 | 1161 | [[package]] 1162 | name = "local-waker" 1163 | version = "0.1.1" 1164 | source = "registry+https://github.com/rust-lang/crates.io-index" 1165 | checksum = "84f9a2d3e27ce99ce2c3aad0b09b1a7b916293ea9b2bf624c13fe646fadd8da4" 1166 | 1167 | [[package]] 1168 | name = "lock_api" 1169 | version = "0.4.4" 1170 | source = "registry+https://github.com/rust-lang/crates.io-index" 1171 | checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" 1172 | dependencies = [ 1173 | "scopeguard", 1174 | ] 1175 | 1176 | [[package]] 1177 | name = "log" 1178 | version = "0.4.14" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 1181 | dependencies = [ 1182 | "cfg-if", 1183 | ] 1184 | 1185 | [[package]] 1186 | name = "maplit" 1187 | version = "1.0.2" 1188 | source = "registry+https://github.com/rust-lang/crates.io-index" 1189 | checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" 1190 | 1191 | [[package]] 1192 | name = "matchers" 1193 | version = "0.0.1" 1194 | source = "registry+https://github.com/rust-lang/crates.io-index" 1195 | checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" 1196 | dependencies = [ 1197 | "regex-automata", 1198 | ] 1199 | 1200 | [[package]] 1201 | name = "matches" 1202 | version = "0.1.8" 1203 | source = "registry+https://github.com/rust-lang/crates.io-index" 1204 | checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1205 | 1206 | [[package]] 1207 | name = "memchr" 1208 | version = "2.4.0" 1209 | source = "registry+https://github.com/rust-lang/crates.io-index" 1210 | checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" 1211 | 1212 | [[package]] 1213 | name = "memoffset" 1214 | version = "0.6.5" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 1217 | dependencies = [ 1218 | "autocfg", 1219 | ] 1220 | 1221 | [[package]] 1222 | name = "mime" 1223 | version = "0.3.16" 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" 1225 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1226 | 1227 | [[package]] 1228 | name = "miniz_oxide" 1229 | version = "0.4.4" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 1232 | dependencies = [ 1233 | "adler", 1234 | "autocfg", 1235 | ] 1236 | 1237 | [[package]] 1238 | name = "mio" 1239 | version = "0.7.13" 1240 | source = "registry+https://github.com/rust-lang/crates.io-index" 1241 | checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" 1242 | dependencies = [ 1243 | "libc", 1244 | "log", 1245 | "miow", 1246 | "ntapi", 1247 | "winapi", 1248 | ] 1249 | 1250 | [[package]] 1251 | name = "mio" 1252 | version = "0.8.0" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" 1255 | dependencies = [ 1256 | "libc", 1257 | "log", 1258 | "miow", 1259 | "ntapi", 1260 | "winapi", 1261 | ] 1262 | 1263 | [[package]] 1264 | name = "miow" 1265 | version = "0.3.7" 1266 | source = "registry+https://github.com/rust-lang/crates.io-index" 1267 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 1268 | dependencies = [ 1269 | "winapi", 1270 | ] 1271 | 1272 | [[package]] 1273 | name = "multimap" 1274 | version = "0.8.3" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" 1277 | 1278 | [[package]] 1279 | name = "mycelium" 1280 | version = "0.4.0" 1281 | dependencies = [ 1282 | "actix-rt", 1283 | "actix-web", 1284 | "anyhow", 1285 | "base64", 1286 | "chrono", 1287 | "futures", 1288 | "k8s-openapi", 1289 | "kube", 1290 | "kube-runtime", 1291 | "linked-hash-map", 1292 | "maplit", 1293 | "nix", 1294 | "opentelemetry", 1295 | "opentelemetry-otlp", 1296 | "prometheus", 1297 | "reqwest", 1298 | "schemars", 1299 | "serde", 1300 | "serde_json", 1301 | "serde_yaml", 1302 | "sha2", 1303 | "signal-hook", 1304 | "thiserror", 1305 | "tokio", 1306 | "toml_edit", 1307 | "tracing", 1308 | "tracing-opentelemetry", 1309 | "tracing-subscriber", 1310 | "yaml-rust", 1311 | ] 1312 | 1313 | [[package]] 1314 | name = "native-tls" 1315 | version = "0.2.8" 1316 | source = "registry+https://github.com/rust-lang/crates.io-index" 1317 | checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" 1318 | dependencies = [ 1319 | "lazy_static", 1320 | "libc", 1321 | "log", 1322 | "openssl", 1323 | "openssl-probe", 1324 | "openssl-sys", 1325 | "schannel", 1326 | "security-framework", 1327 | "security-framework-sys", 1328 | "tempfile", 1329 | ] 1330 | 1331 | [[package]] 1332 | name = "nix" 1333 | version = "0.23.1" 1334 | source = "registry+https://github.com/rust-lang/crates.io-index" 1335 | checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" 1336 | dependencies = [ 1337 | "bitflags", 1338 | "cc", 1339 | "cfg-if", 1340 | "libc", 1341 | "memoffset", 1342 | ] 1343 | 1344 | [[package]] 1345 | name = "ntapi" 1346 | version = "0.3.6" 1347 | source = "registry+https://github.com/rust-lang/crates.io-index" 1348 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 1349 | dependencies = [ 1350 | "winapi", 1351 | ] 1352 | 1353 | [[package]] 1354 | name = "num-integer" 1355 | version = "0.1.44" 1356 | source = "registry+https://github.com/rust-lang/crates.io-index" 1357 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 1358 | dependencies = [ 1359 | "autocfg", 1360 | "num-traits", 1361 | ] 1362 | 1363 | [[package]] 1364 | name = "num-traits" 1365 | version = "0.2.14" 1366 | source = "registry+https://github.com/rust-lang/crates.io-index" 1367 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 1368 | dependencies = [ 1369 | "autocfg", 1370 | ] 1371 | 1372 | [[package]] 1373 | name = "num_cpus" 1374 | version = "1.13.0" 1375 | source = "registry+https://github.com/rust-lang/crates.io-index" 1376 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 1377 | dependencies = [ 1378 | "hermit-abi", 1379 | "libc", 1380 | ] 1381 | 1382 | [[package]] 1383 | name = "once_cell" 1384 | version = "1.8.0" 1385 | source = "registry+https://github.com/rust-lang/crates.io-index" 1386 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 1387 | 1388 | [[package]] 1389 | name = "opaque-debug" 1390 | version = "0.3.0" 1391 | source = "registry+https://github.com/rust-lang/crates.io-index" 1392 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 1393 | 1394 | [[package]] 1395 | name = "openssl" 1396 | version = "0.10.38" 1397 | source = "registry+https://github.com/rust-lang/crates.io-index" 1398 | checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" 1399 | dependencies = [ 1400 | "bitflags", 1401 | "cfg-if", 1402 | "foreign-types", 1403 | "libc", 1404 | "once_cell", 1405 | "openssl-sys", 1406 | ] 1407 | 1408 | [[package]] 1409 | name = "openssl-probe" 1410 | version = "0.1.4" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" 1413 | 1414 | [[package]] 1415 | name = "openssl-sys" 1416 | version = "0.9.72" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" 1419 | dependencies = [ 1420 | "autocfg", 1421 | "cc", 1422 | "libc", 1423 | "pkg-config", 1424 | "vcpkg", 1425 | ] 1426 | 1427 | [[package]] 1428 | name = "opentelemetry" 1429 | version = "0.13.0" 1430 | source = "registry+https://github.com/rust-lang/crates.io-index" 1431 | checksum = "b91cea1dfd50064e52db033179952d18c770cbc5dfefc8eba45d619357ba3914" 1432 | dependencies = [ 1433 | "async-trait", 1434 | "futures", 1435 | "js-sys", 1436 | "lazy_static", 1437 | "percent-encoding", 1438 | "pin-project", 1439 | "rand", 1440 | "thiserror", 1441 | "tokio", 1442 | "tokio-stream", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "opentelemetry-otlp" 1447 | version = "0.6.0" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "09c19adec09e1d86bdc72cbc2dea6d7276d90d6d50ad430842446382a4ef440b" 1450 | dependencies = [ 1451 | "async-trait", 1452 | "futures", 1453 | "opentelemetry", 1454 | "prost", 1455 | "thiserror", 1456 | "tokio", 1457 | "tonic", 1458 | "tonic-build", 1459 | ] 1460 | 1461 | [[package]] 1462 | name = "ordered-float" 1463 | version = "2.6.0" 1464 | source = "registry+https://github.com/rust-lang/crates.io-index" 1465 | checksum = "6dea6388d3d5498ec651701f14edbaf463c924b5d8829fb2848ccf0bcc7b3c69" 1466 | dependencies = [ 1467 | "num-traits", 1468 | ] 1469 | 1470 | [[package]] 1471 | name = "parking_lot" 1472 | version = "0.11.1" 1473 | source = "registry+https://github.com/rust-lang/crates.io-index" 1474 | checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" 1475 | dependencies = [ 1476 | "instant", 1477 | "lock_api", 1478 | "parking_lot_core", 1479 | ] 1480 | 1481 | [[package]] 1482 | name = "parking_lot_core" 1483 | version = "0.8.3" 1484 | source = "registry+https://github.com/rust-lang/crates.io-index" 1485 | checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" 1486 | dependencies = [ 1487 | "cfg-if", 1488 | "instant", 1489 | "libc", 1490 | "redox_syscall", 1491 | "smallvec", 1492 | "winapi", 1493 | ] 1494 | 1495 | [[package]] 1496 | name = "paste" 1497 | version = "1.0.5" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" 1500 | 1501 | [[package]] 1502 | name = "pem" 1503 | version = "1.0.1" 1504 | source = "registry+https://github.com/rust-lang/crates.io-index" 1505 | checksum = "06673860db84d02a63942fa69cd9543f2624a5df3aea7f33173048fa7ad5cf1a" 1506 | dependencies = [ 1507 | "base64", 1508 | "once_cell", 1509 | "regex", 1510 | ] 1511 | 1512 | [[package]] 1513 | name = "percent-encoding" 1514 | version = "2.1.0" 1515 | source = "registry+https://github.com/rust-lang/crates.io-index" 1516 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1517 | 1518 | [[package]] 1519 | name = "pest" 1520 | version = "2.1.3" 1521 | source = "registry+https://github.com/rust-lang/crates.io-index" 1522 | checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" 1523 | dependencies = [ 1524 | "ucd-trie", 1525 | ] 1526 | 1527 | [[package]] 1528 | name = "petgraph" 1529 | version = "0.5.1" 1530 | source = "registry+https://github.com/rust-lang/crates.io-index" 1531 | checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" 1532 | dependencies = [ 1533 | "fixedbitset", 1534 | "indexmap", 1535 | ] 1536 | 1537 | [[package]] 1538 | name = "pin-project" 1539 | version = "1.0.7" 1540 | source = "registry+https://github.com/rust-lang/crates.io-index" 1541 | checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" 1542 | dependencies = [ 1543 | "pin-project-internal", 1544 | ] 1545 | 1546 | [[package]] 1547 | name = "pin-project-internal" 1548 | version = "1.0.7" 1549 | source = "registry+https://github.com/rust-lang/crates.io-index" 1550 | checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" 1551 | dependencies = [ 1552 | "proc-macro2", 1553 | "quote", 1554 | "syn", 1555 | ] 1556 | 1557 | [[package]] 1558 | name = "pin-project-lite" 1559 | version = "0.2.7" 1560 | source = "registry+https://github.com/rust-lang/crates.io-index" 1561 | checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" 1562 | 1563 | [[package]] 1564 | name = "pin-utils" 1565 | version = "0.1.0" 1566 | source = "registry+https://github.com/rust-lang/crates.io-index" 1567 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1568 | 1569 | [[package]] 1570 | name = "pkg-config" 1571 | version = "0.3.19" 1572 | source = "registry+https://github.com/rust-lang/crates.io-index" 1573 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 1574 | 1575 | [[package]] 1576 | name = "ppv-lite86" 1577 | version = "0.2.10" 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" 1579 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 1580 | 1581 | [[package]] 1582 | name = "proc-macro-hack" 1583 | version = "0.5.19" 1584 | source = "registry+https://github.com/rust-lang/crates.io-index" 1585 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 1586 | 1587 | [[package]] 1588 | name = "proc-macro2" 1589 | version = "1.0.34" 1590 | source = "registry+https://github.com/rust-lang/crates.io-index" 1591 | checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" 1592 | dependencies = [ 1593 | "unicode-xid", 1594 | ] 1595 | 1596 | [[package]] 1597 | name = "prometheus" 1598 | version = "0.12.0" 1599 | source = "registry+https://github.com/rust-lang/crates.io-index" 1600 | checksum = "5986aa8d62380092d2f50f8b1cdba9cb9b6731ffd4b25b51fd126b6c3e05b99c" 1601 | dependencies = [ 1602 | "cfg-if", 1603 | "fnv", 1604 | "lazy_static", 1605 | "memchr", 1606 | "parking_lot", 1607 | "protobuf", 1608 | "thiserror", 1609 | ] 1610 | 1611 | [[package]] 1612 | name = "prost" 1613 | version = "0.7.0" 1614 | source = "registry+https://github.com/rust-lang/crates.io-index" 1615 | checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2" 1616 | dependencies = [ 1617 | "bytes", 1618 | "prost-derive", 1619 | ] 1620 | 1621 | [[package]] 1622 | name = "prost-build" 1623 | version = "0.7.0" 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" 1625 | checksum = "32d3ebd75ac2679c2af3a92246639f9fcc8a442ee420719cc4fe195b98dd5fa3" 1626 | dependencies = [ 1627 | "bytes", 1628 | "heck", 1629 | "itertools 0.9.0", 1630 | "log", 1631 | "multimap", 1632 | "petgraph", 1633 | "prost", 1634 | "prost-types", 1635 | "tempfile", 1636 | "which", 1637 | ] 1638 | 1639 | [[package]] 1640 | name = "prost-derive" 1641 | version = "0.7.0" 1642 | source = "registry+https://github.com/rust-lang/crates.io-index" 1643 | checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4" 1644 | dependencies = [ 1645 | "anyhow", 1646 | "itertools 0.9.0", 1647 | "proc-macro2", 1648 | "quote", 1649 | "syn", 1650 | ] 1651 | 1652 | [[package]] 1653 | name = "prost-types" 1654 | version = "0.7.0" 1655 | source = "registry+https://github.com/rust-lang/crates.io-index" 1656 | checksum = "b518d7cdd93dab1d1122cf07fa9a60771836c668dde9d9e2a139f957f0d9f1bb" 1657 | dependencies = [ 1658 | "bytes", 1659 | "prost", 1660 | ] 1661 | 1662 | [[package]] 1663 | name = "protobuf" 1664 | version = "2.24.1" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "db50e77ae196458ccd3dc58a31ea1a90b0698ab1b7928d89f644c25d72070267" 1667 | 1668 | [[package]] 1669 | name = "quote" 1670 | version = "1.0.10" 1671 | source = "registry+https://github.com/rust-lang/crates.io-index" 1672 | checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" 1673 | dependencies = [ 1674 | "proc-macro2", 1675 | ] 1676 | 1677 | [[package]] 1678 | name = "rand" 1679 | version = "0.8.4" 1680 | source = "registry+https://github.com/rust-lang/crates.io-index" 1681 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 1682 | dependencies = [ 1683 | "libc", 1684 | "rand_chacha", 1685 | "rand_core", 1686 | "rand_hc", 1687 | ] 1688 | 1689 | [[package]] 1690 | name = "rand_chacha" 1691 | version = "0.3.1" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1694 | dependencies = [ 1695 | "ppv-lite86", 1696 | "rand_core", 1697 | ] 1698 | 1699 | [[package]] 1700 | name = "rand_core" 1701 | version = "0.6.3" 1702 | source = "registry+https://github.com/rust-lang/crates.io-index" 1703 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 1704 | dependencies = [ 1705 | "getrandom", 1706 | ] 1707 | 1708 | [[package]] 1709 | name = "rand_hc" 1710 | version = "0.3.1" 1711 | source = "registry+https://github.com/rust-lang/crates.io-index" 1712 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 1713 | dependencies = [ 1714 | "rand_core", 1715 | ] 1716 | 1717 | [[package]] 1718 | name = "redox_syscall" 1719 | version = "0.2.9" 1720 | source = "registry+https://github.com/rust-lang/crates.io-index" 1721 | checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" 1722 | dependencies = [ 1723 | "bitflags", 1724 | ] 1725 | 1726 | [[package]] 1727 | name = "redox_users" 1728 | version = "0.4.0" 1729 | source = "registry+https://github.com/rust-lang/crates.io-index" 1730 | checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" 1731 | dependencies = [ 1732 | "getrandom", 1733 | "redox_syscall", 1734 | ] 1735 | 1736 | [[package]] 1737 | name = "regex" 1738 | version = "1.5.4" 1739 | source = "registry+https://github.com/rust-lang/crates.io-index" 1740 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 1741 | dependencies = [ 1742 | "aho-corasick", 1743 | "memchr", 1744 | "regex-syntax", 1745 | ] 1746 | 1747 | [[package]] 1748 | name = "regex-automata" 1749 | version = "0.1.10" 1750 | source = "registry+https://github.com/rust-lang/crates.io-index" 1751 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 1752 | dependencies = [ 1753 | "regex-syntax", 1754 | ] 1755 | 1756 | [[package]] 1757 | name = "regex-syntax" 1758 | version = "0.6.25" 1759 | source = "registry+https://github.com/rust-lang/crates.io-index" 1760 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 1761 | 1762 | [[package]] 1763 | name = "remove_dir_all" 1764 | version = "0.5.3" 1765 | source = "registry+https://github.com/rust-lang/crates.io-index" 1766 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 1767 | dependencies = [ 1768 | "winapi", 1769 | ] 1770 | 1771 | [[package]] 1772 | name = "reqwest" 1773 | version = "0.11.8" 1774 | source = "registry+https://github.com/rust-lang/crates.io-index" 1775 | checksum = "7c4e0a76dc12a116108933f6301b95e83634e0c47b0afbed6abbaa0601e99258" 1776 | dependencies = [ 1777 | "base64", 1778 | "bytes", 1779 | "encoding_rs", 1780 | "futures-core", 1781 | "futures-util", 1782 | "http", 1783 | "http-body", 1784 | "hyper", 1785 | "hyper-tls", 1786 | "ipnet", 1787 | "js-sys", 1788 | "lazy_static", 1789 | "log", 1790 | "mime", 1791 | "native-tls", 1792 | "percent-encoding", 1793 | "pin-project-lite", 1794 | "serde", 1795 | "serde_json", 1796 | "serde_urlencoded", 1797 | "tokio", 1798 | "tokio-native-tls", 1799 | "url", 1800 | "wasm-bindgen", 1801 | "wasm-bindgen-futures", 1802 | "web-sys", 1803 | "winreg", 1804 | ] 1805 | 1806 | [[package]] 1807 | name = "rustc_version" 1808 | version = "0.2.3" 1809 | source = "registry+https://github.com/rust-lang/crates.io-index" 1810 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1811 | dependencies = [ 1812 | "semver 0.9.0", 1813 | ] 1814 | 1815 | [[package]] 1816 | name = "rustc_version" 1817 | version = "0.3.3" 1818 | source = "registry+https://github.com/rust-lang/crates.io-index" 1819 | checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" 1820 | dependencies = [ 1821 | "semver 0.11.0", 1822 | ] 1823 | 1824 | [[package]] 1825 | name = "ryu" 1826 | version = "1.0.5" 1827 | source = "registry+https://github.com/rust-lang/crates.io-index" 1828 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1829 | 1830 | [[package]] 1831 | name = "schannel" 1832 | version = "0.1.19" 1833 | source = "registry+https://github.com/rust-lang/crates.io-index" 1834 | checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" 1835 | dependencies = [ 1836 | "lazy_static", 1837 | "winapi", 1838 | ] 1839 | 1840 | [[package]] 1841 | name = "schemars" 1842 | version = "0.8.8" 1843 | source = "registry+https://github.com/rust-lang/crates.io-index" 1844 | checksum = "c6b5a3c80cea1ab61f4260238409510e814e38b4b563c06044edf91e7dc070e3" 1845 | dependencies = [ 1846 | "chrono", 1847 | "dyn-clone", 1848 | "schemars_derive", 1849 | "serde", 1850 | "serde_json", 1851 | ] 1852 | 1853 | [[package]] 1854 | name = "schemars_derive" 1855 | version = "0.8.8" 1856 | source = "registry+https://github.com/rust-lang/crates.io-index" 1857 | checksum = "41ae4dce13e8614c46ac3c38ef1c0d668b101df6ac39817aebdaa26642ddae9b" 1858 | dependencies = [ 1859 | "proc-macro2", 1860 | "quote", 1861 | "serde_derive_internals", 1862 | "syn", 1863 | ] 1864 | 1865 | [[package]] 1866 | name = "scopeguard" 1867 | version = "1.1.0" 1868 | source = "registry+https://github.com/rust-lang/crates.io-index" 1869 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1870 | 1871 | [[package]] 1872 | name = "security-framework" 1873 | version = "2.3.1" 1874 | source = "registry+https://github.com/rust-lang/crates.io-index" 1875 | checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" 1876 | dependencies = [ 1877 | "bitflags", 1878 | "core-foundation", 1879 | "core-foundation-sys", 1880 | "libc", 1881 | "security-framework-sys", 1882 | ] 1883 | 1884 | [[package]] 1885 | name = "security-framework-sys" 1886 | version = "2.3.0" 1887 | source = "registry+https://github.com/rust-lang/crates.io-index" 1888 | checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284" 1889 | dependencies = [ 1890 | "core-foundation-sys", 1891 | "libc", 1892 | ] 1893 | 1894 | [[package]] 1895 | name = "semver" 1896 | version = "0.9.0" 1897 | source = "registry+https://github.com/rust-lang/crates.io-index" 1898 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1899 | dependencies = [ 1900 | "semver-parser 0.7.0", 1901 | ] 1902 | 1903 | [[package]] 1904 | name = "semver" 1905 | version = "0.11.0" 1906 | source = "registry+https://github.com/rust-lang/crates.io-index" 1907 | checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" 1908 | dependencies = [ 1909 | "semver-parser 0.10.2", 1910 | ] 1911 | 1912 | [[package]] 1913 | name = "semver-parser" 1914 | version = "0.7.0" 1915 | source = "registry+https://github.com/rust-lang/crates.io-index" 1916 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1917 | 1918 | [[package]] 1919 | name = "semver-parser" 1920 | version = "0.10.2" 1921 | source = "registry+https://github.com/rust-lang/crates.io-index" 1922 | checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" 1923 | dependencies = [ 1924 | "pest", 1925 | ] 1926 | 1927 | [[package]] 1928 | name = "serde" 1929 | version = "1.0.132" 1930 | source = "registry+https://github.com/rust-lang/crates.io-index" 1931 | checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" 1932 | dependencies = [ 1933 | "serde_derive", 1934 | ] 1935 | 1936 | [[package]] 1937 | name = "serde-value" 1938 | version = "0.7.0" 1939 | source = "registry+https://github.com/rust-lang/crates.io-index" 1940 | checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" 1941 | dependencies = [ 1942 | "ordered-float", 1943 | "serde", 1944 | ] 1945 | 1946 | [[package]] 1947 | name = "serde_derive" 1948 | version = "1.0.132" 1949 | source = "registry+https://github.com/rust-lang/crates.io-index" 1950 | checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" 1951 | dependencies = [ 1952 | "proc-macro2", 1953 | "quote", 1954 | "syn", 1955 | ] 1956 | 1957 | [[package]] 1958 | name = "serde_derive_internals" 1959 | version = "0.25.0" 1960 | source = "registry+https://github.com/rust-lang/crates.io-index" 1961 | checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" 1962 | dependencies = [ 1963 | "proc-macro2", 1964 | "quote", 1965 | "syn", 1966 | ] 1967 | 1968 | [[package]] 1969 | name = "serde_json" 1970 | version = "1.0.73" 1971 | source = "registry+https://github.com/rust-lang/crates.io-index" 1972 | checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" 1973 | dependencies = [ 1974 | "indexmap", 1975 | "itoa 1.0.1", 1976 | "ryu", 1977 | "serde", 1978 | ] 1979 | 1980 | [[package]] 1981 | name = "serde_urlencoded" 1982 | version = "0.7.0" 1983 | source = "registry+https://github.com/rust-lang/crates.io-index" 1984 | checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" 1985 | dependencies = [ 1986 | "form_urlencoded", 1987 | "itoa 0.4.7", 1988 | "ryu", 1989 | "serde", 1990 | ] 1991 | 1992 | [[package]] 1993 | name = "serde_yaml" 1994 | version = "0.8.23" 1995 | source = "registry+https://github.com/rust-lang/crates.io-index" 1996 | checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" 1997 | dependencies = [ 1998 | "indexmap", 1999 | "ryu", 2000 | "serde", 2001 | "yaml-rust", 2002 | ] 2003 | 2004 | [[package]] 2005 | name = "sha-1" 2006 | version = "0.9.6" 2007 | source = "registry+https://github.com/rust-lang/crates.io-index" 2008 | checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16" 2009 | dependencies = [ 2010 | "block-buffer 0.9.0", 2011 | "cfg-if", 2012 | "cpufeatures 0.1.5", 2013 | "digest 0.9.0", 2014 | "opaque-debug", 2015 | ] 2016 | 2017 | [[package]] 2018 | name = "sha1" 2019 | version = "0.6.0" 2020 | source = "registry+https://github.com/rust-lang/crates.io-index" 2021 | checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" 2022 | 2023 | [[package]] 2024 | name = "sha2" 2025 | version = "0.10.0" 2026 | source = "registry+https://github.com/rust-lang/crates.io-index" 2027 | checksum = "900d964dd36bb15bcf2f2b35694c072feab74969a54f2bbeec7a2d725d2bdcb6" 2028 | dependencies = [ 2029 | "cfg-if", 2030 | "cpufeatures 0.2.1", 2031 | "digest 0.10.1", 2032 | ] 2033 | 2034 | [[package]] 2035 | name = "sharded-slab" 2036 | version = "0.1.1" 2037 | source = "registry+https://github.com/rust-lang/crates.io-index" 2038 | checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3" 2039 | dependencies = [ 2040 | "lazy_static", 2041 | ] 2042 | 2043 | [[package]] 2044 | name = "signal-hook" 2045 | version = "0.3.13" 2046 | source = "registry+https://github.com/rust-lang/crates.io-index" 2047 | checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" 2048 | dependencies = [ 2049 | "libc", 2050 | "signal-hook-registry", 2051 | ] 2052 | 2053 | [[package]] 2054 | name = "signal-hook-registry" 2055 | version = "1.4.0" 2056 | source = "registry+https://github.com/rust-lang/crates.io-index" 2057 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 2058 | dependencies = [ 2059 | "libc", 2060 | ] 2061 | 2062 | [[package]] 2063 | name = "slab" 2064 | version = "0.4.3" 2065 | source = "registry+https://github.com/rust-lang/crates.io-index" 2066 | checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" 2067 | 2068 | [[package]] 2069 | name = "smallvec" 2070 | version = "1.7.0" 2071 | source = "registry+https://github.com/rust-lang/crates.io-index" 2072 | checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" 2073 | 2074 | [[package]] 2075 | name = "socket2" 2076 | version = "0.4.2" 2077 | source = "registry+https://github.com/rust-lang/crates.io-index" 2078 | checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" 2079 | dependencies = [ 2080 | "libc", 2081 | "winapi", 2082 | ] 2083 | 2084 | [[package]] 2085 | name = "standback" 2086 | version = "0.2.17" 2087 | source = "registry+https://github.com/rust-lang/crates.io-index" 2088 | checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" 2089 | dependencies = [ 2090 | "version_check", 2091 | ] 2092 | 2093 | [[package]] 2094 | name = "stdweb" 2095 | version = "0.4.20" 2096 | source = "registry+https://github.com/rust-lang/crates.io-index" 2097 | checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" 2098 | dependencies = [ 2099 | "discard", 2100 | "rustc_version 0.2.3", 2101 | "stdweb-derive", 2102 | "stdweb-internal-macros", 2103 | "stdweb-internal-runtime", 2104 | "wasm-bindgen", 2105 | ] 2106 | 2107 | [[package]] 2108 | name = "stdweb-derive" 2109 | version = "0.5.3" 2110 | source = "registry+https://github.com/rust-lang/crates.io-index" 2111 | checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" 2112 | dependencies = [ 2113 | "proc-macro2", 2114 | "quote", 2115 | "serde", 2116 | "serde_derive", 2117 | "syn", 2118 | ] 2119 | 2120 | [[package]] 2121 | name = "stdweb-internal-macros" 2122 | version = "0.2.9" 2123 | source = "registry+https://github.com/rust-lang/crates.io-index" 2124 | checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" 2125 | dependencies = [ 2126 | "base-x", 2127 | "proc-macro2", 2128 | "quote", 2129 | "serde", 2130 | "serde_derive", 2131 | "serde_json", 2132 | "sha1", 2133 | "syn", 2134 | ] 2135 | 2136 | [[package]] 2137 | name = "stdweb-internal-runtime" 2138 | version = "0.1.5" 2139 | source = "registry+https://github.com/rust-lang/crates.io-index" 2140 | checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" 2141 | 2142 | [[package]] 2143 | name = "strsim" 2144 | version = "0.10.0" 2145 | source = "registry+https://github.com/rust-lang/crates.io-index" 2146 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2147 | 2148 | [[package]] 2149 | name = "syn" 2150 | version = "1.0.82" 2151 | source = "registry+https://github.com/rust-lang/crates.io-index" 2152 | checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" 2153 | dependencies = [ 2154 | "proc-macro2", 2155 | "quote", 2156 | "unicode-xid", 2157 | ] 2158 | 2159 | [[package]] 2160 | name = "tempfile" 2161 | version = "3.2.0" 2162 | source = "registry+https://github.com/rust-lang/crates.io-index" 2163 | checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" 2164 | dependencies = [ 2165 | "cfg-if", 2166 | "libc", 2167 | "rand", 2168 | "redox_syscall", 2169 | "remove_dir_all", 2170 | "winapi", 2171 | ] 2172 | 2173 | [[package]] 2174 | name = "thiserror" 2175 | version = "1.0.30" 2176 | source = "registry+https://github.com/rust-lang/crates.io-index" 2177 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 2178 | dependencies = [ 2179 | "thiserror-impl", 2180 | ] 2181 | 2182 | [[package]] 2183 | name = "thiserror-impl" 2184 | version = "1.0.30" 2185 | source = "registry+https://github.com/rust-lang/crates.io-index" 2186 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 2187 | dependencies = [ 2188 | "proc-macro2", 2189 | "quote", 2190 | "syn", 2191 | ] 2192 | 2193 | [[package]] 2194 | name = "thread_local" 2195 | version = "1.1.3" 2196 | source = "registry+https://github.com/rust-lang/crates.io-index" 2197 | checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" 2198 | dependencies = [ 2199 | "once_cell", 2200 | ] 2201 | 2202 | [[package]] 2203 | name = "time" 2204 | version = "0.1.44" 2205 | source = "registry+https://github.com/rust-lang/crates.io-index" 2206 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 2207 | dependencies = [ 2208 | "libc", 2209 | "wasi", 2210 | "winapi", 2211 | ] 2212 | 2213 | [[package]] 2214 | name = "time" 2215 | version = "0.2.27" 2216 | source = "registry+https://github.com/rust-lang/crates.io-index" 2217 | checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" 2218 | dependencies = [ 2219 | "const_fn", 2220 | "libc", 2221 | "standback", 2222 | "stdweb", 2223 | "time-macros", 2224 | "version_check", 2225 | "winapi", 2226 | ] 2227 | 2228 | [[package]] 2229 | name = "time" 2230 | version = "0.3.5" 2231 | source = "registry+https://github.com/rust-lang/crates.io-index" 2232 | checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" 2233 | dependencies = [ 2234 | "itoa 0.4.7", 2235 | "libc", 2236 | ] 2237 | 2238 | [[package]] 2239 | name = "time-macros" 2240 | version = "0.1.1" 2241 | source = "registry+https://github.com/rust-lang/crates.io-index" 2242 | checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" 2243 | dependencies = [ 2244 | "proc-macro-hack", 2245 | "time-macros-impl", 2246 | ] 2247 | 2248 | [[package]] 2249 | name = "time-macros-impl" 2250 | version = "0.1.2" 2251 | source = "registry+https://github.com/rust-lang/crates.io-index" 2252 | checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" 2253 | dependencies = [ 2254 | "proc-macro-hack", 2255 | "proc-macro2", 2256 | "quote", 2257 | "standback", 2258 | "syn", 2259 | ] 2260 | 2261 | [[package]] 2262 | name = "tinyvec" 2263 | version = "1.2.0" 2264 | source = "registry+https://github.com/rust-lang/crates.io-index" 2265 | checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" 2266 | dependencies = [ 2267 | "tinyvec_macros", 2268 | ] 2269 | 2270 | [[package]] 2271 | name = "tinyvec_macros" 2272 | version = "0.1.0" 2273 | source = "registry+https://github.com/rust-lang/crates.io-index" 2274 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 2275 | 2276 | [[package]] 2277 | name = "tokio" 2278 | version = "1.15.0" 2279 | source = "registry+https://github.com/rust-lang/crates.io-index" 2280 | checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" 2281 | dependencies = [ 2282 | "bytes", 2283 | "libc", 2284 | "memchr", 2285 | "mio 0.7.13", 2286 | "num_cpus", 2287 | "once_cell", 2288 | "parking_lot", 2289 | "pin-project-lite", 2290 | "signal-hook-registry", 2291 | "tokio-macros", 2292 | "winapi", 2293 | ] 2294 | 2295 | [[package]] 2296 | name = "tokio-io-timeout" 2297 | version = "1.1.1" 2298 | source = "registry+https://github.com/rust-lang/crates.io-index" 2299 | checksum = "90c49f106be240de154571dd31fbe48acb10ba6c6dd6f6517ad603abffa42de9" 2300 | dependencies = [ 2301 | "pin-project-lite", 2302 | "tokio", 2303 | ] 2304 | 2305 | [[package]] 2306 | name = "tokio-macros" 2307 | version = "1.7.0" 2308 | source = "registry+https://github.com/rust-lang/crates.io-index" 2309 | checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" 2310 | dependencies = [ 2311 | "proc-macro2", 2312 | "quote", 2313 | "syn", 2314 | ] 2315 | 2316 | [[package]] 2317 | name = "tokio-native-tls" 2318 | version = "0.3.0" 2319 | source = "registry+https://github.com/rust-lang/crates.io-index" 2320 | checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" 2321 | dependencies = [ 2322 | "native-tls", 2323 | "tokio", 2324 | ] 2325 | 2326 | [[package]] 2327 | name = "tokio-stream" 2328 | version = "0.1.7" 2329 | source = "registry+https://github.com/rust-lang/crates.io-index" 2330 | checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" 2331 | dependencies = [ 2332 | "futures-core", 2333 | "pin-project-lite", 2334 | "tokio", 2335 | ] 2336 | 2337 | [[package]] 2338 | name = "tokio-util" 2339 | version = "0.6.9" 2340 | source = "registry+https://github.com/rust-lang/crates.io-index" 2341 | checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" 2342 | dependencies = [ 2343 | "bytes", 2344 | "futures-core", 2345 | "futures-sink", 2346 | "log", 2347 | "pin-project-lite", 2348 | "slab", 2349 | "tokio", 2350 | ] 2351 | 2352 | [[package]] 2353 | name = "toml_edit" 2354 | version = "0.12.1" 2355 | source = "registry+https://github.com/rust-lang/crates.io-index" 2356 | checksum = "25321ef4c481482d05675fde4ac4bcfcf91f589de5ca266608e1340bf56d8c79" 2357 | dependencies = [ 2358 | "combine", 2359 | "indexmap", 2360 | "itertools 0.10.3", 2361 | "kstring", 2362 | ] 2363 | 2364 | [[package]] 2365 | name = "tonic" 2366 | version = "0.4.3" 2367 | source = "registry+https://github.com/rust-lang/crates.io-index" 2368 | checksum = "2ac42cd97ac6bd2339af5bcabf105540e21e45636ec6fa6aae5e85d44db31be0" 2369 | dependencies = [ 2370 | "async-stream", 2371 | "async-trait", 2372 | "base64", 2373 | "bytes", 2374 | "futures-core", 2375 | "futures-util", 2376 | "h2", 2377 | "http", 2378 | "http-body", 2379 | "hyper", 2380 | "percent-encoding", 2381 | "pin-project", 2382 | "prost", 2383 | "prost-derive", 2384 | "tokio", 2385 | "tokio-stream", 2386 | "tokio-util", 2387 | "tower", 2388 | "tower-service", 2389 | "tracing", 2390 | "tracing-futures", 2391 | ] 2392 | 2393 | [[package]] 2394 | name = "tonic-build" 2395 | version = "0.4.2" 2396 | source = "registry+https://github.com/rust-lang/crates.io-index" 2397 | checksum = "c695de27302f4697191dda1c7178131a8cb805463dda02864acb80fe1322fdcf" 2398 | dependencies = [ 2399 | "proc-macro2", 2400 | "prost-build", 2401 | "quote", 2402 | "syn", 2403 | ] 2404 | 2405 | [[package]] 2406 | name = "tower" 2407 | version = "0.4.8" 2408 | source = "registry+https://github.com/rust-lang/crates.io-index" 2409 | checksum = "f60422bc7fefa2f3ec70359b8ff1caff59d785877eb70595904605bcc412470f" 2410 | dependencies = [ 2411 | "futures-core", 2412 | "futures-util", 2413 | "indexmap", 2414 | "pin-project", 2415 | "rand", 2416 | "slab", 2417 | "tokio", 2418 | "tokio-stream", 2419 | "tokio-util", 2420 | "tower-layer", 2421 | "tower-service", 2422 | "tracing", 2423 | ] 2424 | 2425 | [[package]] 2426 | name = "tower-http" 2427 | version = "0.2.0" 2428 | source = "registry+https://github.com/rust-lang/crates.io-index" 2429 | checksum = "39ee603d6e665ecc7e0f8d479eedb4626bd4726f0ee6119cee5b3a6bf184cac0" 2430 | dependencies = [ 2431 | "base64", 2432 | "bitflags", 2433 | "bytes", 2434 | "futures-core", 2435 | "futures-util", 2436 | "http", 2437 | "http-body", 2438 | "http-range-header", 2439 | "pin-project-lite", 2440 | "tower-layer", 2441 | "tower-service", 2442 | "tracing", 2443 | ] 2444 | 2445 | [[package]] 2446 | name = "tower-layer" 2447 | version = "0.3.1" 2448 | source = "registry+https://github.com/rust-lang/crates.io-index" 2449 | checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" 2450 | 2451 | [[package]] 2452 | name = "tower-service" 2453 | version = "0.3.1" 2454 | source = "registry+https://github.com/rust-lang/crates.io-index" 2455 | checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" 2456 | 2457 | [[package]] 2458 | name = "tracing" 2459 | version = "0.1.29" 2460 | source = "registry+https://github.com/rust-lang/crates.io-index" 2461 | checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" 2462 | dependencies = [ 2463 | "cfg-if", 2464 | "log", 2465 | "pin-project-lite", 2466 | "tracing-attributes", 2467 | "tracing-core", 2468 | ] 2469 | 2470 | [[package]] 2471 | name = "tracing-attributes" 2472 | version = "0.1.18" 2473 | source = "registry+https://github.com/rust-lang/crates.io-index" 2474 | checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" 2475 | dependencies = [ 2476 | "proc-macro2", 2477 | "quote", 2478 | "syn", 2479 | ] 2480 | 2481 | [[package]] 2482 | name = "tracing-core" 2483 | version = "0.1.21" 2484 | source = "registry+https://github.com/rust-lang/crates.io-index" 2485 | checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" 2486 | dependencies = [ 2487 | "lazy_static", 2488 | ] 2489 | 2490 | [[package]] 2491 | name = "tracing-futures" 2492 | version = "0.2.5" 2493 | source = "registry+https://github.com/rust-lang/crates.io-index" 2494 | checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" 2495 | dependencies = [ 2496 | "pin-project", 2497 | "tracing", 2498 | ] 2499 | 2500 | [[package]] 2501 | name = "tracing-log" 2502 | version = "0.1.2" 2503 | source = "registry+https://github.com/rust-lang/crates.io-index" 2504 | checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" 2505 | dependencies = [ 2506 | "lazy_static", 2507 | "log", 2508 | "tracing-core", 2509 | ] 2510 | 2511 | [[package]] 2512 | name = "tracing-opentelemetry" 2513 | version = "0.12.0" 2514 | source = "registry+https://github.com/rust-lang/crates.io-index" 2515 | checksum = "99003208b647dae59dcefc49c98aecaa3512fbc29351685d4b9ef23a9218458e" 2516 | dependencies = [ 2517 | "opentelemetry", 2518 | "tracing", 2519 | "tracing-core", 2520 | "tracing-log", 2521 | "tracing-subscriber", 2522 | ] 2523 | 2524 | [[package]] 2525 | name = "tracing-serde" 2526 | version = "0.1.2" 2527 | source = "registry+https://github.com/rust-lang/crates.io-index" 2528 | checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" 2529 | dependencies = [ 2530 | "serde", 2531 | "tracing-core", 2532 | ] 2533 | 2534 | [[package]] 2535 | name = "tracing-subscriber" 2536 | version = "0.2.19" 2537 | source = "registry+https://github.com/rust-lang/crates.io-index" 2538 | checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48" 2539 | dependencies = [ 2540 | "ansi_term", 2541 | "chrono", 2542 | "lazy_static", 2543 | "matchers", 2544 | "regex", 2545 | "serde", 2546 | "serde_json", 2547 | "sharded-slab", 2548 | "smallvec", 2549 | "thread_local", 2550 | "tracing", 2551 | "tracing-core", 2552 | "tracing-log", 2553 | "tracing-serde", 2554 | ] 2555 | 2556 | [[package]] 2557 | name = "treediff" 2558 | version = "3.0.2" 2559 | source = "registry+https://github.com/rust-lang/crates.io-index" 2560 | checksum = "761e8d5ad7ce14bb82b7e61ccc0ca961005a275a060b9644a2431aa11553c2ff" 2561 | dependencies = [ 2562 | "serde_json", 2563 | ] 2564 | 2565 | [[package]] 2566 | name = "try-lock" 2567 | version = "0.2.3" 2568 | source = "registry+https://github.com/rust-lang/crates.io-index" 2569 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 2570 | 2571 | [[package]] 2572 | name = "typenum" 2573 | version = "1.13.0" 2574 | source = "registry+https://github.com/rust-lang/crates.io-index" 2575 | checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" 2576 | 2577 | [[package]] 2578 | name = "ucd-trie" 2579 | version = "0.1.3" 2580 | source = "registry+https://github.com/rust-lang/crates.io-index" 2581 | checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" 2582 | 2583 | [[package]] 2584 | name = "unicode-bidi" 2585 | version = "0.3.5" 2586 | source = "registry+https://github.com/rust-lang/crates.io-index" 2587 | checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" 2588 | dependencies = [ 2589 | "matches", 2590 | ] 2591 | 2592 | [[package]] 2593 | name = "unicode-normalization" 2594 | version = "0.1.19" 2595 | source = "registry+https://github.com/rust-lang/crates.io-index" 2596 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 2597 | dependencies = [ 2598 | "tinyvec", 2599 | ] 2600 | 2601 | [[package]] 2602 | name = "unicode-segmentation" 2603 | version = "1.8.0" 2604 | source = "registry+https://github.com/rust-lang/crates.io-index" 2605 | checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" 2606 | 2607 | [[package]] 2608 | name = "unicode-xid" 2609 | version = "0.2.2" 2610 | source = "registry+https://github.com/rust-lang/crates.io-index" 2611 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 2612 | 2613 | [[package]] 2614 | name = "url" 2615 | version = "2.2.2" 2616 | source = "registry+https://github.com/rust-lang/crates.io-index" 2617 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 2618 | dependencies = [ 2619 | "form_urlencoded", 2620 | "idna", 2621 | "matches", 2622 | "percent-encoding", 2623 | ] 2624 | 2625 | [[package]] 2626 | name = "vcpkg" 2627 | version = "0.2.15" 2628 | source = "registry+https://github.com/rust-lang/crates.io-index" 2629 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2630 | 2631 | [[package]] 2632 | name = "version_check" 2633 | version = "0.9.3" 2634 | source = "registry+https://github.com/rust-lang/crates.io-index" 2635 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 2636 | 2637 | [[package]] 2638 | name = "want" 2639 | version = "0.3.0" 2640 | source = "registry+https://github.com/rust-lang/crates.io-index" 2641 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 2642 | dependencies = [ 2643 | "log", 2644 | "try-lock", 2645 | ] 2646 | 2647 | [[package]] 2648 | name = "wasi" 2649 | version = "0.10.0+wasi-snapshot-preview1" 2650 | source = "registry+https://github.com/rust-lang/crates.io-index" 2651 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 2652 | 2653 | [[package]] 2654 | name = "wasm-bindgen" 2655 | version = "0.2.74" 2656 | source = "registry+https://github.com/rust-lang/crates.io-index" 2657 | checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" 2658 | dependencies = [ 2659 | "cfg-if", 2660 | "wasm-bindgen-macro", 2661 | ] 2662 | 2663 | [[package]] 2664 | name = "wasm-bindgen-backend" 2665 | version = "0.2.74" 2666 | source = "registry+https://github.com/rust-lang/crates.io-index" 2667 | checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" 2668 | dependencies = [ 2669 | "bumpalo", 2670 | "lazy_static", 2671 | "log", 2672 | "proc-macro2", 2673 | "quote", 2674 | "syn", 2675 | "wasm-bindgen-shared", 2676 | ] 2677 | 2678 | [[package]] 2679 | name = "wasm-bindgen-futures" 2680 | version = "0.4.24" 2681 | source = "registry+https://github.com/rust-lang/crates.io-index" 2682 | checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" 2683 | dependencies = [ 2684 | "cfg-if", 2685 | "js-sys", 2686 | "wasm-bindgen", 2687 | "web-sys", 2688 | ] 2689 | 2690 | [[package]] 2691 | name = "wasm-bindgen-macro" 2692 | version = "0.2.74" 2693 | source = "registry+https://github.com/rust-lang/crates.io-index" 2694 | checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" 2695 | dependencies = [ 2696 | "quote", 2697 | "wasm-bindgen-macro-support", 2698 | ] 2699 | 2700 | [[package]] 2701 | name = "wasm-bindgen-macro-support" 2702 | version = "0.2.74" 2703 | source = "registry+https://github.com/rust-lang/crates.io-index" 2704 | checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" 2705 | dependencies = [ 2706 | "proc-macro2", 2707 | "quote", 2708 | "syn", 2709 | "wasm-bindgen-backend", 2710 | "wasm-bindgen-shared", 2711 | ] 2712 | 2713 | [[package]] 2714 | name = "wasm-bindgen-shared" 2715 | version = "0.2.74" 2716 | source = "registry+https://github.com/rust-lang/crates.io-index" 2717 | checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" 2718 | 2719 | [[package]] 2720 | name = "web-sys" 2721 | version = "0.3.51" 2722 | source = "registry+https://github.com/rust-lang/crates.io-index" 2723 | checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" 2724 | dependencies = [ 2725 | "js-sys", 2726 | "wasm-bindgen", 2727 | ] 2728 | 2729 | [[package]] 2730 | name = "which" 2731 | version = "4.1.0" 2732 | source = "registry+https://github.com/rust-lang/crates.io-index" 2733 | checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe" 2734 | dependencies = [ 2735 | "either", 2736 | "libc", 2737 | ] 2738 | 2739 | [[package]] 2740 | name = "winapi" 2741 | version = "0.3.9" 2742 | source = "registry+https://github.com/rust-lang/crates.io-index" 2743 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2744 | dependencies = [ 2745 | "winapi-i686-pc-windows-gnu", 2746 | "winapi-x86_64-pc-windows-gnu", 2747 | ] 2748 | 2749 | [[package]] 2750 | name = "winapi-i686-pc-windows-gnu" 2751 | version = "0.4.0" 2752 | source = "registry+https://github.com/rust-lang/crates.io-index" 2753 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2754 | 2755 | [[package]] 2756 | name = "winapi-x86_64-pc-windows-gnu" 2757 | version = "0.4.0" 2758 | source = "registry+https://github.com/rust-lang/crates.io-index" 2759 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2760 | 2761 | [[package]] 2762 | name = "winreg" 2763 | version = "0.7.0" 2764 | source = "registry+https://github.com/rust-lang/crates.io-index" 2765 | checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" 2766 | dependencies = [ 2767 | "winapi", 2768 | ] 2769 | 2770 | [[package]] 2771 | name = "yaml-rust" 2772 | version = "0.4.5" 2773 | source = "registry+https://github.com/rust-lang/crates.io-index" 2774 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" 2775 | dependencies = [ 2776 | "linked-hash-map", 2777 | ] 2778 | 2779 | [[package]] 2780 | name = "zstd" 2781 | version = "0.9.0+zstd.1.5.0" 2782 | source = "registry+https://github.com/rust-lang/crates.io-index" 2783 | checksum = "07749a5dc2cb6b36661290245e350f15ec3bbb304e493db54a1d354480522ccd" 2784 | dependencies = [ 2785 | "zstd-safe", 2786 | ] 2787 | 2788 | [[package]] 2789 | name = "zstd-safe" 2790 | version = "4.1.1+zstd.1.5.0" 2791 | source = "registry+https://github.com/rust-lang/crates.io-index" 2792 | checksum = "c91c90f2c593b003603e5e0493c837088df4469da25aafff8bce42ba48caf079" 2793 | dependencies = [ 2794 | "libc", 2795 | "zstd-sys", 2796 | ] 2797 | 2798 | [[package]] 2799 | name = "zstd-sys" 2800 | version = "1.6.1+zstd.1.5.0" 2801 | source = "registry+https://github.com/rust-lang/crates.io-index" 2802 | checksum = "615120c7a2431d16cf1cf979e7fc31ba7a5b5e5707b29c8a99e5dbf8a8392a33" 2803 | dependencies = [ 2804 | "cc", 2805 | "libc", 2806 | ] 2807 | --------------------------------------------------------------------------------