domain

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ToolTierStable     = "stable"
	ToolTierBeta       = "beta"
	ToolTierDeprecated = "deprecated"
)

Tool tier constants describe the per-tool maturity level inside a matrix.

View Source
const (
	ArchAMD64 = "amd64"
	ArchARM64 = "arm64"
)

Node architecture constants used for per-tool ArchSupport.

View Source
const (
	// ProvisionedPostgresSecret 은 설치가 만드는 PostgreSQL 자격증명이다.
	ProvisionedPostgresSecret = "nullus-postgresql-credentials"
	// ProvisionedMinIOSecret 은 설치가 만드는 MinIO 자격증명이다.
	ProvisionedMinIOSecret = "nullus-minio-credentials"
	// ProvisionedObjectStorageSecret 은 GitLab 의 object_store 연결 정보다.
	ProvisionedObjectStorageSecret = "nullus-object-storage"
	// ProvisionedRegistryStorageSecret 은 Container Registry 의 S3 설정이다.
	ProvisionedRegistryStorageSecret = "nullus-registry-storage" // #nosec G101 -- Secret 리소스 이름

	// MinIORootUser 는 비밀이 아니지만 차트의 existingSecret 이 같은 Secret
	// 안에서 요구하므로 함께 프로비저닝한다.
	MinIORootUser = "nullus-admin"

	// PostgresAppUser / PostgresAppDatabase 는 GitLab 이 쓰는 계정과 DB 다.
	PostgresAppUser     = "gitlab"
	PostgresAppDatabase = "gitlabhq_production"

	// PostgresPasswordKey 는 앱 계정 비밀번호 키다.
	// postgres-password 는 superuser 용이라 앱 접속에는 쓰지 않는다.
	PostgresPasswordKey = "password"
	// MinIOUserKey / MinIOPasswordKey 는 charts.min.io 의 existingSecret 이
	// 읽는 키 이름이다. 프로비저닝과 안내가 같은 키를 봐야 한다.
	MinIOUserKey     = "rootUser"
	MinIOPasswordKey = "rootPassword"

	// PostgresServiceName / MinIOServiceName 은 Helm 릴리스명에서 온다.
	// 네임스페이스와 무관하므로 네임스페이스로 조립하면 안 된다.
	// 릴리스명 자체는 admin 의 시크릿 회전도 봐야 하므로 shared 가 소유한다.
	PostgresServiceName = shareddomain.PostgresReleaseName
	PostgresServicePort = 5432
	MinIOServiceName    = shareddomain.MinIOReleaseName
	MinIOServicePort    = 9000

	// MinIO 콘솔(웹 UI)은 API 와 다른 Service·포트를 쓴다.
	MinIOConsoleServiceName = MinIOServiceName + "-console"
	MinIOConsoleServicePort = 9001

	// GitLabArtifactsBucket 은 설치가 만드는 아티팩트 버킷이다.
	// 연결정보가 오브젝트 스토리지의 resource_name 으로 안내한다.
	GitLabArtifactsBucket = "gitlab-artifacts"
)

설치가 만들어내는 리소스 이름들. 여기가 단일 출처다.

이 값들은 두 곳에서 필요하다 — 설치 경로(Helm values 가 existingSecret 으로 참조)와 조회 경로(사용자에게 접속 방법을 안내). 양쪽에 각각 적어 두면 한쪽만 바뀌었을 때 조용히 어긋나고, 화면은 존재하지 않는 이름을 계속 안내한다. 실제로 UI 가 `-n nullus get secret argo-cd-argocd-initial-admin-secret` 을 안내하다가 NotFound 를 내던 사고가 있었다.

View Source
const (
	// HarborServiceName 은 Harbor 진입 Service 다. expose.type=clusterIP 로
	// 설치하면 차트가 릴리스명과 같은 이름의 Service 를 만들고, 여기로 들어온
	// 요청을 portal/core 로 갈라 보낸다. 이미지 push/pull 도 이 주소를 쓴다.
	HarborReleaseName  = "harbor"
	HarborServiceName  = HarborReleaseName
	HarborServicePort  = 80
	HarborAdminUser    = "admin"
	HarborAdminSecret  = "nullus-harbor-credentials" // #nosec G101 -- Secret 리소스 이름
	HarborAdminPassKey = "HARBOR_ADMIN_PASSWORD"     // 차트의 existingSecretAdminPasswordKey 기본값

	// NexusServiceName 은 Nexus 진입 Service 다. 차트 기본 이름은
	// {release}-nexus-repository-manager 라 길어지므로 fullnameOverride 로 맞춘다.
	NexusReleaseName = "nexus"
	NexusServiceName = NexusReleaseName
	// NexusServicePort 는 웹 UI 와 Maven/npm 저장소가 함께 쓰는 포트다.
	NexusServicePort = 8081
	// NexusDockerServicePort 는 Docker 레지스트리 커넥터 포트다. Nexus 는
	// Docker 레지스트리를 별도 HTTP 커넥터로 노출하며 기본값이 없다 —
	// provisioning_nexus 단계가 이 포트로 커넥터를 만들고 Service 를 덧붙인다.
	NexusDockerServicePort = 8082
	NexusAdminUser         = "admin"
	NexusAdminSecret       = "nullus-nexus-credentials" // #nosec G101 -- Secret 리소스 이름
	NexusAdminPassKey      = "password"

	// Nexus 가 만드는 저장소 이름. CI 가 이미지를 올리고 빌드가 패키지를
	// 받아가는 곳이라 설치와 파이프라인이 같은 이름을 봐야 한다.
	NexusDockerRepository = "docker-hosted"
	NexusMavenRepository  = "maven-hosted"
	NexusNpmRepository    = "npm-hosted"

	// GiteaReleaseName 은 Gitea 릴리스명이다. 릴리스명이 곧 파드 이름 접두사이자
	// Service 이름의 뿌리가 되므로, 워크로드 조회와 in-cluster 주소가 같은 값을 본다.
	GiteaReleaseName = "gitea"
	// GiteaHTTPServiceName 은 Gitea 차트가 만드는 HTTP 진입 Service 다.
	// 차트가 {release}-http 로 이름을 유도한다 — CI/CD 모듈이 이 주소로 API 를 부른다.
	GiteaHTTPServiceName = GiteaReleaseName + "-http"

	// 접속 도메인용 와일드카드 TLS. 설치가 게이트웨이 HTTPS 리스너를 위해 만들고
	// 삭제가 이름으로 지운다 — 그 매니페스트의 라벨은 stack.Name 이 아니라 접속
	// 도메인에서 오므로 라벨 셀렉터로는 잡히지 않는다.
	// usecase 가 adapter 를 import 하면 레이어 방향이 뒤집히므로 여기 둔다.
	AccessDomainCertName      = "nullus-access-domain-cert"
	AccessDomainTLSSecretName = "nullus-access-domain-tls"
	GiteaServicePort          = 3000
	GiteaAdminUser            = "gitea_admin"
	// GiteaAdminSecret 은 gitea.admin.existingSecret 이 참조하는 Secret 이다.
	// 차트는 이 안에서 username / password 키를 읽는다
	// (templates/gitea/deployment.yaml — GITEA_ADMIN_USERNAME / GITEA_ADMIN_PASSWORD).
	GiteaAdminSecret      = "nullus-gitea-credentials" // #nosec G101 -- Secret 리소스 이름
	GiteaAdminUserKey     = "username"
	GiteaAdminPasswordKey = "password"

	// JenkinsReleaseName 은 Jenkins 릴리스명이다. 파드 접두사이자 Service 이름의
	// 뿌리가 된다 — CI/CD 모듈이 이 주소로 job 을 만든다.
	JenkinsReleaseName = "jenkins"
	JenkinsServiceName = JenkinsReleaseName
	JenkinsServicePort = 8080
	JenkinsAdminUser   = "admin"
	// JenkinsAdminSecret 은 controller.admin.existingSecret 이 참조하는 Secret 이다.
	// 차트가 읽는 키 이름은 controller.admin.userKey / passwordKey 기본값과 같아야
	// 한다 — 틀리면 파드가 FailedMount 로 영원히 기동하지 못한다.
	JenkinsAdminSecret      = "nullus-jenkins-credentials" // #nosec G101 -- Secret 리소스 이름
	JenkinsAdminUserKey     = "jenkins-admin-user"
	JenkinsAdminPasswordKey = "jenkins-admin-password"
)

독립 설치형 아티팩트 도구(Harbor / Nexus)의 리소스 이름.

GitLab 내장 레지스트리와 달리 이 둘은 자체 릴리스로 선다. 서비스 이름은 차트가 릴리스명에서 유도하므로 릴리스명이 곧 in-cluster 주소가 된다.

View Source
const (
	HarborChartVersion = "1.15.0"
	HarborAppVersion   = "2.11.0"
	NexusChartVersion  = "64.2.0"
	NexusAppVersion    = "3.64.0"

	// GitLab 차트 하나가 소스 저장소·CI·컨테이너 레지스트리를 함께 세운다.
	// 세 항목이 같은 버전을 봐야 한다.
	GitLabChartVersion = "8.7.2"
	GitLabAppVersion   = "v17.7.0"

	// Gitea 는 소스 저장소만 담당한다 — GitLab 과 달리 CI 도 레지스트리도 겸하지
	// 않으므로, 이 스택은 CI(Jenkins)와 레지스트리(Harbor)를 따로 세운다.
	GiteaChartVersion = "12.7.0"
	GiteaAppVersion   = "1.27.0"

	// Jenkins 차트 버전은 자유롭게 내릴 수 없다. Gitea multibranch 스캔에 쓰는
	// jenkinsci/gitea 플러그인이 Jenkins 2.528.3 이상을 요구하므로, appVersion 이
	// 그 하한을 넘는 차트여야 한다. 5.9.54 → 2.568.2 로 요건을 만족한다.
	// (고정: TestJenkinsAppVersion_SatisfiesGiteaPluginMinimum)
	JenkinsChartVersion = "5.9.54"
	JenkinsAppVersion   = "2.568.2"
	// JenkinsGiteaPluginMinAppVersion 은 gitea 플러그인이 요구하는 Jenkins 하한이다.
	JenkinsGiteaPluginMinAppVersion = "2.528.3"

	MinIOChartVersion = "5.4.0"
	MinIOAppVersion   = "RELEASE.2024-12-18T13-15-44Z"

	ArgoCDChartVersion = "7.7.16"
	ArgoCDAppVersion   = "v2.13.3"

	// kube-prometheus-stack 의 appVersion 은 prometheus-operator 버전(v0.80.0)이라
	// 그대로 쓰면 화면에 오퍼레이터 버전이 Prometheus 버전인 양 뜬다. 사용자가
	// 알아야 하는 것은 실제로 서는 Prometheus 서버 버전이므로 그것을 적는다.
	PrometheusChartVersion = "69.3.0"
	// PrometheusOperatorCRDsChartVersion 은 위 차트가 쓰는 operator(v0.80.0)와
	// 같은 버전의 CRD 를 담는다. ServiceMonitor / Probe 를 만드는 단계가
	// kube-prometheus-stack 설치보다 앞서므로 CRD 를 먼저 깐다.
	PrometheusOperatorCRDsChartVersion = "18.0.0"
	PrometheusAppVersion               = "v3.1.0"

	GrafanaChartVersion = "8.9.0"
	GrafanaAppVersion   = "11.5.1"

	// 추적 저장소. 차트 기본값으로 OTLP 수신기(4317/4318)가 켜져 있어
	// 수집기가 별도 설정 없이 곧바로 보낼 수 있다.
	TempoChartVersion = "1.18.1"
	TempoAppVersion   = "2.7.0"

	// OpenTelemetry Collector. 차트 0.75.0 의 appVersion 은 0.90.0 이다 —
	// 프론트 기본값(0.104.0)이 차트와 갈라져 있었으므로 차트를 기준으로 삼는다.
	OTelCollectorChartVersion = "0.75.0"
	OTelCollectorAppVersion   = "0.90.0"
)

설치가 사용하는 차트 버전.

화면은 호환성 매트릭스가 선언한 버전을 보여주고 설치는 이 값을 쓴다. 둘이 갈라지면 "안내된 버전"과 "설치된 버전"이 달라지므로 같은 값을 봐야 한다. (고정: TestChartVersionsMatchCompatibilityMatrix) AppVersion 은 그 차트가 실제로 세우는 제품 버전이다. 차트의 appVersion 필드를 그대로 옮기지 않은 곳이 하나 있다 — 아래 Prometheus 주석 참고.

View Source
const (
	OTelCollectorReleaseName  = shareddomain.OTelCollectorReleaseName
	OTelAgentReleaseName      = shareddomain.OTelAgentReleaseName
	OTelCollectorOTLPGRPCPort = shareddomain.OTelCollectorOTLPGRPCPort
	OTelCollectorOTLPHTTPPort = shareddomain.OTelCollectorOTLPHTTPPort
)

OpenTelemetry 수집기의 이름·주소 규칙은 shared 가 소유한다.

cicd 는 배포하는 앱에 이 주소를 넣어 줘야 하는데, 모듈끼리 서로의 internal 을 참조할 수 없어 규칙을 shared 에 두고 양쪽이 같은 것을 본다. 여기서는 stack 코드가 계속 domain 이름으로 쓰도록 별칭만 남긴다.

View Source
const (
	ArgoCDAdminSecret   = "argocd-initial-admin-secret" // #nosec G101 -- Secret 리소스 이름
	ArgoCDAdminUser     = "admin"
	ArgoCDAdminPassKey  = "password"
	GitLabRootSecret    = "gitlab-gitlab-initial-root-password" // #nosec G101 -- Secret 리소스 이름
	GitLabRootUser      = "root"
	GitLabRootPassKey   = "password"
	GrafanaAdminUser    = "admin"
	OpenSearchAdminUser = "admin"
)

OSS 도구의 초기 자격증명이 담기는 Secret.

차트마다 이름 규칙이 다르다 — Argo CD 는 Deployment/Service 에는 릴리스 접두사를 붙이지만 Secret 에는 붙이지 않는다.

View Source
const (
	SlotPackageRegistry         = "artifacts.packageRegistry"
	SlotSourceRepository        = "artifacts.sourceRepository"
	SlotContainerRegistry       = "artifacts.containerRegistry"
	SlotStorageBackend          = "artifacts.storageBackend"
	SlotCICDPlatform            = "pipeline.cicdPlatform"
	SlotCDTool                  = "pipeline.cdTool"
	SlotMonitoringCollection    = "monitoring.collection"
	SlotMonitoringVisualization = "monitoring.visualization"
	SlotLogSearch               = "logging.search"
	SlotTraceLayer              = "logging.traceLayer"
	SlotTraceExporter           = "logging.traceExporter"
)

계획 슬롯. 도구 이름이 아니라 자리로 잇는다 — 이름은 gitlab / gitlab-ce 처럼 출처마다 흔들리지만 자리는 흔들리지 않는다.

View Source
const (
	PlanningProfileLocal      = "local"
	PlanningProfileStartup    = "startup"
	PlanningProfileStandard   = "standard"
	PlanningProfileEnterprise = "enterprise"
)

설치 규모 프로파일. 설치 마법사의 리소스 계획이 이 값에서 시작한다.

템플릿이 이 값을 들고 다니는 이유는, 도구 선택만으로는 스택이 몇 Gi 를 먹을지 정해지지 않기 때문이다 — 같은 Gitea+Jenkins+Argo CD 라도 standard 로 깔면 8Gi 노드에 들어가지 않는다. "무엇을 깔지"와 "얼마나 크게 깔지"는 함께 정해져야 한다.

View Source
const DefaultStackNamespace = shareddomain.DefaultStackNamespace

DefaultStackNamespace 는 스택 네임스페이스가 정해지지 않았을 때의 기본값이다. 설치 경로와 안내 경로가 같은 값을 봐야 하므로 domain 이 소유한다.

View Source
const StaleInstallThreshold = 30 * time.Minute

StaleInstallThreshold 는 이만큼 아무 진전이 없으면 끊긴 것으로 본다.

한 스텝이 오래 걸릴 수 있다 — GitLab 은 helm --wait 타임아웃만 15분이다. 그 동안에는 행이 갱신되지 않으므로 여유를 크게 잡는다. 너무 짧게 잡으면 살아 있는 설치를 실패로 표시해 버린다.

Variables

View Source
var InstallStepOrder = []string{
	"installing_cert_manager",
	"installing_prometheus_crds",
	"installing_metrics_server",
	"installing_openbao",
	"installing_external_secrets",
	"provisioning_secrets",
	"installing_postgresql",
	"installing_minio",
	"installing_object_storage_secret",
	"installing_object_storage_buckets",
	"installing_database_connection_check",
	"provisioning_sso",
	"installing_gitlab",
	"installing_gitea",
	"provisioning_gitea",
	"installing_harbor",
	"provisioning_harbor",
	"installing_nexus",
	"provisioning_nexus",
	"installing_argocd",
	"installing_runner",
	"installing_jenkins",
	"installing_prometheus",
	"installing_grafana",
	"installing_logging",
	"installing_log_search",
	"installing_opentelemetry",
	"installing_otel_collector",
	"installing_otel_agent",
	"installing_gateway",
	"integration_check",
}

설치가 밟는 단계의 순서. 진행률의 단일 출처다.

예전에는 화면(단계 5개)과 서버(손으로 적은 스텝→퍼센트 표)가 각자 값을 갖고 있었다. 표에는 provisioning_secrets·installing_postgresql·installing_gitea 처럼 실제로 밟는 스텝의 절반이 빠져 있어서, 그 스텝에서는 진행률이 0 으로 나왔다. 그러면 화면이 다른 근거로 값을 지어내고, 시크릿만 깔린 시점에 막대가 절반을 넘긴 것처럼 보였다.

순서는 오케스트레이터가 실제로 도는 순서와 같아야 한다 — 그쪽이 이 목록을 그대로 쓴다.

View Source
var InstalledHelmReleaseNames = []string{
	"cert-manager",

	"prometheus-operator-crds",
	"metrics-server",
	"openbao",
	"external-secrets",
	"nullus-postgresql",
	"nullus-minio",

	HarborReleaseName,
	NexusReleaseName,

	"gitlab",
	GiteaReleaseName,
	"argo-cd",

	"gitlab-runner",
	JenkinsReleaseName,
	"kube-prometheus-stack",
	"grafana",
	"loki",

	"opensearch",
	"elasticsearch",

	"opentelemetry-collector",
	"tempo",
	"jaeger",

	OTelCollectorReleaseName,

	OTelAgentReleaseName,
	"eg",
}

InstalledHelmReleaseNames 는 스택 설치가 만들어 내는 모든 Helm 릴리스다. 로깅/트레이스처럼 설정에 따라 차트가 갈리는 단계는 가능한 변형을 모두 포함한다.

View Source
var LegacyHelmReleaseNames = []string{
	"postgresql",
	"minio",
	"envoy-gateway",
}

LegacyHelmReleaseNames 는 과거 이름으로 설치된 스택을 지우기 위해 남겨 둔다. 설치 경로는 더 이상 이 이름을 쓰지 않는다.

View Source
var PlanningOptionDefs = map[string][]PlanningOptionDef{
	SlotPackageRegistry: {
		{Key: "registryCallsPerDay", Baseline: 3000, Min: 500, Max: 50000, Weight: 0.45, Impact: ResourceImpact{CPU: 1, Memory: 0.8, Storage: 0.3}},
		{Key: "avgArtifactSizeMb", Baseline: 120, Min: 10, Max: 2000, Weight: 0.25, Impact: ResourceImpact{CPU: 0.1, Memory: 0.2, Storage: 1}},
		{Key: "retentionDays", Baseline: 30, Min: 1, Max: 365, Weight: 0.30, Impact: ResourceImpact{CPU: 0, Memory: 0.1, Storage: 1}},
	},
	SlotSourceRepository: {
		{Key: "activeRepoUsers", Baseline: 20, Min: 5, Max: 500, Weight: 0.4, Impact: ResourceImpact{CPU: 0.8, Memory: 0.6, Storage: 0.3}},
		{Key: "repoCount", Baseline: 60, Min: 5, Max: 3000, Weight: 0.35, Impact: ResourceImpact{CPU: 0.2, Memory: 0.4, Storage: 1}},
		{Key: "dailyPushEvents", Baseline: 250, Min: 20, Max: 20000, Weight: 0.25, Impact: ResourceImpact{CPU: 1, Memory: 0.5, Storage: 0.4}},
	},
	SlotContainerRegistry: {
		{Key: "imagePullsPerDay", Baseline: 2000, Min: 200, Max: 100000, Weight: 0.4, Impact: ResourceImpact{CPU: 0.8, Memory: 0.7, Storage: 0.4}},
		{Key: "newImagePushesPerDay", Baseline: 180, Min: 10, Max: 8000, Weight: 0.35, Impact: ResourceImpact{CPU: 0.9, Memory: 0.6, Storage: 0.8}},
		{Key: "avgImageSizeGb", Baseline: 1.2, Min: 0.1, Max: 20, Weight: 0.25, Impact: ResourceImpact{CPU: 0.1, Memory: 0.2, Storage: 1}},
	},
	SlotStorageBackend: {
		{Key: "objectOpsPerDay", Baseline: 10000, Min: 1000, Max: 200000, Weight: 0.45, Impact: ResourceImpact{CPU: 0.9, Memory: 0.8, Storage: 0.4}},
		{Key: "storedDataTb", Baseline: 1.5, Min: 0.1, Max: 100, Weight: 0.35, Impact: ResourceImpact{CPU: 0.1, Memory: 0.2, Storage: 1}},
		{Key: "backupFrequencyPerWeek", Baseline: 7, Min: 1, Max: 30, Weight: 0.20, Impact: ResourceImpact{CPU: 0.4, Memory: 0.3, Storage: 0.7}},
	},
	SlotCICDPlatform: {
		{Key: "developers", Baseline: 20, Min: 1, Max: 1000, Weight: 0.2, Impact: ResourceImpact{CPU: 0.4, Memory: 0.4, Storage: 0.2}},
		{Key: "concurrentRunners", Baseline: 4, Min: 1, Max: 400, Weight: 0.55, Impact: ResourceImpact{CPU: 1.8, Memory: 1.6, Storage: 0.7}},
		{Key: "dailyCommits", Baseline: 120, Min: 10, Max: 10000, Weight: 0.25, Impact: ResourceImpact{CPU: 0.8, Memory: 0.6, Storage: 0.3}},
	},
	SlotCDTool: {
		{Key: "deploymentsPerDay", Baseline: 40, Min: 1, Max: 2000, Weight: 0.5, Impact: ResourceImpact{CPU: 0.8, Memory: 0.6, Storage: 0.2}},
		{Key: "environmentsCount", Baseline: 4, Min: 1, Max: 30, Weight: 0.25, Impact: ResourceImpact{CPU: 0.4, Memory: 0.5, Storage: 0.3}},
		{Key: "rollbackRatePercent", Baseline: 8, Min: 0, Max: 80, Weight: 0.25, Impact: ResourceImpact{CPU: 0.5, Memory: 0.6, Storage: 0.2}},
	},
	SlotMonitoringCollection: {
		{Key: "metricsTargets", Baseline: 150, Min: 20, Max: 5000, Weight: 0.45, Impact: ResourceImpact{CPU: 0.7, Memory: 0.9, Storage: 0.4}},
		{Key: "scrapeIntervalSec", Baseline: 30, Min: 5, Max: 120, Weight: 0.30, Impact: ResourceImpact{CPU: -0.6, Memory: -0.7, Storage: -0.2}},
		{Key: "retentionDays", Baseline: 15, Min: 1, Max: 365, Weight: 0.25, Impact: ResourceImpact{CPU: 0, Memory: 0.2, Storage: 1}},
	},
	SlotMonitoringVisualization: {
		{Key: "dashboardUsers", Baseline: 30, Min: 5, Max: 2000, Weight: 0.45, Impact: ResourceImpact{CPU: 0.5, Memory: 0.5, Storage: 0.1}},
		{Key: "dashboardCount", Baseline: 40, Min: 5, Max: 1500, Weight: 0.30, Impact: ResourceImpact{CPU: 0.4, Memory: 0.6, Storage: 0.2}},
		{Key: "refreshIntervalSec", Baseline: 30, Min: 5, Max: 300, Weight: 0.25, Impact: ResourceImpact{CPU: -0.5, Memory: -0.4, Storage: -0.1}},
	},
	SlotLogSearch: {
		{Key: "logGbPerDay", Baseline: 100, Min: 5, Max: 10000, Weight: 0.5, Impact: ResourceImpact{CPU: 0.6, Memory: 0.7, Storage: 1}},
		{Key: "retentionDays", Baseline: 30, Min: 1, Max: 365, Weight: 0.3, Impact: ResourceImpact{CPU: 0, Memory: 0.2, Storage: 1}},
		{Key: "queryUsers", Baseline: 20, Min: 1, Max: 1000, Weight: 0.2, Impact: ResourceImpact{CPU: 0.7, Memory: 0.6, Storage: 0.2}},
	},
	SlotTraceLayer: {
		{Key: "traceSpansPerMin", Baseline: 50000, Min: 1000, Max: 3000000, Weight: 0.5, Impact: ResourceImpact{CPU: 0.8, Memory: 0.7, Storage: 0.5}},
		{Key: "serviceCount", Baseline: 40, Min: 5, Max: 2000, Weight: 0.3, Impact: ResourceImpact{CPU: 0.4, Memory: 0.5, Storage: 0.3}},
		{Key: "traceRetentionDays", Baseline: 7, Min: 1, Max: 90, Weight: 0.2, Impact: ResourceImpact{CPU: 0, Memory: 0.2, Storage: 1}},
	},
	SlotTraceExporter: {
		{Key: "traceSpansPerMin", Baseline: 50000, Min: 1000, Max: 3000000, Weight: 0.6, Impact: ResourceImpact{CPU: 0.9, Memory: 0.7, Storage: 0.2}},
		{Key: "serviceCount", Baseline: 40, Min: 5, Max: 2000, Weight: 0.4, Impact: ResourceImpact{CPU: 0.5, Memory: 0.4, Storage: 0.1}},
	},
}

PlanningOptionDefs 는 슬롯별 옵션 정의다.

Functions

func AllHelmReleaseNames

func AllHelmReleaseNames() []string

AllHelmReleaseNames 는 삭제가 훑어야 하는 릴리스 전체다.

func DefaultPlanningOptions

func DefaultPlanningOptions(profile, slot string) map[string]float64

DefaultPlanningOptions 는 사용자가 아무것도 만지지 않은 상태의 옵션값이다. 헤드리스 설치는 언제나 이 상태로 계획한다.

func DefaultStackNamespaceFor

func DefaultStackNamespaceFor(stackName string) string

DefaultStackNamespaceFor 는 스택 이름에서 기본 네임스페이스를 만든다.

예전 기본값은 DefaultStackNamespace("nullus") 하나였고, 그것은 플랫폼 자신이 사는 네임스페이스와 같았다. 그래서 두 가지가 동시에 깨졌다 —

  • 설치: 스택의 PostgreSQL 릴리스(nullus-postgresql)가 플랫폼 차트가 이미 소유한 같은 이름의 리소스와 부딪혀 Helm 이 거부한다.
  • 삭제: 스택 정리가 같은 네임스페이스를 훑으며 플랫폼 리소스를 지운다. 2026-08-20 에 실제로 nullus.io 가 통째로 내려갔다.

스택마다 자기 네임스페이스를 갖게 하면 두 경로 모두 애초에 만나지 않는다.

func IsInFlight

func IsInFlight(state DeploymentState) bool

IsInFlight 는 설치가 진행 중인 상태인지 본다.

func IsStaleInstall

func IsStaleInstall(state DeploymentState, updatedAt, now time.Time) bool

IsStaleInstall 은 진행 중이라고 표시돼 있지만 실제로는 끊긴 설치인지 본다.

설치는 API 프로세스 안의 고루틴이 돌린다. 파드가 교체되면 그 고루틴이 사라지고, 아무도 실패를 기록하지 않는다 — 스택은 installing 인 채로 영원히 남는다. 그 상태에서는 이어서 진행(continue)도 막히므로(failed/pending 만 허용) 사용자에게는 지우고 다시 까는 길밖에 없다. 2026-08-20 운영에서 실제로 그렇게 갇혔다.

살아 있는 설치와 구분할 방법은 시간뿐이다. 여러 레플리카가 도는 환경에서는 "재시작했으니 죽었다" 고 단정할 수 없다.

func NormalizePlanningProfile

func NormalizePlanningProfile(profile string) string

NormalizePlanningProfile 은 공백·대소문자를 흡수하고, 빈 값을 기본 프로파일로 채운다. 아는 값이 아니면 빈 문자열을 돌려준다 — 오타를 조용히 standard 로 바꾸면 8Gi 를 노린 템플릿이 그 두 배로 설치되므로, 판단은 호출자에게 남긴다.

func OTelCollectorOTLPGRPCEndpoint

func OTelCollectorOTLPGRPCEndpoint(namespace string) string

OTelCollectorOTLPGRPCEndpoint 는 애플리케이션이 OTLP/gRPC 로 보낼 주소다.

func OTelCollectorOTLPHTTPEndpoint

func OTelCollectorOTLPHTTPEndpoint(namespace string) string

OTelCollectorOTLPHTTPEndpoint 는 애플리케이션이 OTLP/HTTP 로 보낼 주소다.

func OTelCollectorServiceName

func OTelCollectorServiceName() string

OTelCollectorServiceName 은 수집기 Service 이름이다.

func PlanAppliedResources

func PlanAppliedResources(profile string, cfg StackConfig, baseByToolKey map[string]ResourceVector) map[string]ResourceVector

PlanAppliedResources 는 프로파일과 고른 도구로 applied_resource_overrides 를 만든다. baseByToolKey 는 관리자 기본값(stack_resource_defaults)이다.

기준 벡터가 없는 도구는 건너뛴다 — 0 벡터로 계획하면 requests 가 0 이 되어 파드가 무제한으로 뜨므로, 계획을 안 세우고 차트 기본값에 맡기는 편이 낫다.

func PlanningSlots

func PlanningSlots() []string

PlanningSlots 는 계획 대상 슬롯을 마법사 화면과 같은 순서로 돌려준다.

func ProfileAdjustedBaseline

func ProfileAdjustedBaseline(profile string, def PlanningOptionDef) float64

ProfileAdjustedBaseline 은 프로파일이 적용된 옵션 기본값이다. 마법사가 화면을 열 때 채워 넣는 값과 같다.

func ProfileFactorByOption

func ProfileFactorByOption(profile, optionKey string) float64

ProfileFactorByOption 은 프로파일이 옵션 기본값을 몇 배로 조정하는지 돌려준다.

성격별로 방향이 다르다 — 보관 기간·처리량은 작은 프로파일에서 줄지만, 주기 (interval)는 늘어난다. 주기가 길수록 부하가 줄기 때문이다.

func ProtectedValuePaths

func ProtectedValuePaths(step string) []string

ProtectedValuePaths 는 해당 설치 단계에서 플랫폼이 소유한 values 경로다. 모르는 단계는 빈 슬라이스를 돌려준다 — 보호할 것이 없다는 뜻이다.

func ResourceToolKey

func ResourceToolKey(name string) string

ResourceToolKey 는 도구 표기명을 자원 기본값 표의 키로 옮긴다.

func StackProgress

func StackProgress(state DeploymentState, currentStep, lastCompletedStep string) (progress, ceiling int)

StackProgress 는 저장된 스택 상태만으로 진행률을 되살린다.

새로고침하면 WebSocket 이 처음부터 다시 붙어 그동안의 진행률을 모른다. 예전에는 화면이 상태(installing 등)를 뭉뚱그린 표로 대신 채웠는데, 그 값은 스텝 기반 진행률과 달라서 **새로고침할 때마다 퍼센트가 튀었다**. 같은 계산을 여기서 한 번 더 해 주면 두 경로가 같은 값을 본다.

진행 중인 스텝이 있으면 그 스텝의 값이다. 없으면 마지막으로 끝낸 스텝까지는 갔다는 뜻이므로 그 스텝의 상한을 쓴다.

func StepProgress

func StepProgress(step string) int

StepProgress 는 그 스텝을 밟는 동안 보여 줄 진행률이다.

설치 스텝은 5~90 을 균등하게 나눠 갖는다. 스텝 하나가 끝나면 딱 그만큼 오른다 — 시간이 아니라 실제로 한 일에 맞춰 움직인다.

모르는 스텝은 -1 이다. 0 을 돌려주면 "아직 시작 전" 과 구분되지 않아, 화면이 진행률을 다른 근거로 지어내게 된다.

func StepProgressCeiling

func StepProgressCeiling(step string) int

StepProgressCeiling 은 그 스텝이 끝났을 때 닿을 값이다.

화면은 이 값을 상한으로 삼아 스텝 안에서만 조금씩 움직인다 — 다음 스텝의 몫까지 미리 채우면 하지 않은 일을 한 것처럼 보여 준다.

func ToolAccessURL

func ToolAccessURL(toolName, accessDomain string) string

ToolAccessURL 은 스택 접속 도메인 위에 선 OSS 하나의 웹 주소다.

주소 규칙이 단일 출처여야 하는 이유는 화면이 여러 개이기 때문이다 — 스택 상세 화면, 모니터링 대시보드, 연결정보 안내가 모두 "Grafana 는 어디로 들어가는가"를 답해야 한다. 각자 조립하면 한 곳만 바뀌었을 때 조용히 갈라지고, 사용자는 화면마다 다른 주소를 본다.

스킴은 항상 https 다. 접속 도메인은 게이트웨이 TLS 리스너 뒤에 서고, 임베드 탭도 https 를 전제로 정규화한다 — 여기서 http 를 내려주면 브라우저가 혼합 콘텐츠로 막거나 리다이렉트 한 번을 더 타게 된다.

주소를 모르는 도구는 빈 문자열을 돌려준다. 그럴듯한 호스트를 지어내면 화면이 죽은 링크를 안내하게 되므로, 모를 때는 링크를 걸지 않는 편이 낫다.

func ValidateAccessDomain

func ValidateAccessDomain(accessDomain string) error

ValidateAccessDomain 은 접속 도메인이 실제로 라우팅·발급에 쓸 수 있는 값인지 본다.

이 값 하나가 스택의 모든 주소가 된다 — HTTPRoute 의 hostname("gitlab.<도메인>"), 게이트웨이 인증서의 commonName 과 dnsNames("*.<도메인>"), 도구들의 redirect_uri. 그래서 형식이 깨지면 설치는 끝나도 아무것도 열리지 않는다.

2026-08-20 운영 스택은 access_domain 이 ".io" 로 저장돼 있었다. 만들어진 매니페스트는 hostname "jenkins..io", 인증서 dnsNames "*..io" 였다. 아무도 막지 않아서 설치 절차를 다 태운 뒤에야 드러났다.

Types

type AccessDomainTLSConfig

type AccessDomainTLSConfig struct {
	Enabled         bool   `json:"enabled"`
	SecretName      string `json:"secret_name,omitempty"`
	SecretNamespace string `json:"secret_namespace,omitempty"`
	IssuerName      string `json:"issuer_name,omitempty"`
}

type ArtifactsConfig

type ArtifactsConfig struct {
	PackageRegistry   ToolSelection `json:"package_registry"`
	SourceRepository  ToolSelection `json:"source_repository"`
	ContainerRegistry ToolSelection `json:"container_registry"`
	StorageBackend    ToolSelection `json:"storage_backend"`
}

ArtifactsConfig holds tool selections for the artifacts step.

type AuthenticationConfig

type AuthenticationConfig struct {
	Provider string `json:"provider,omitempty"`
}

type CompatibilityMatrix

type CompatibilityMatrix struct {
	ID         string
	Name       string
	Status     string // verified | untested | unsupported
	Kubernetes KubernetesCompat
	Tools      map[string]ToolVersion
}

CompatibilityMatrix represents a verified or untested tool combination matrix.

type ConfigDiff

type ConfigDiff struct {
	Field    string
	OldValue string
	NewValue string
}

ConfigDiff describes a single field change between two stack versions.

type ConnectionInfo

type ConnectionInfo struct {
	StackID       string            `json:"stack_id"`
	Namespace     string            `json:"namespace"`
	AccessDomain  string            `json:"access_domain,omitempty"`
	Database      StorageConnection `json:"database"`
	ObjectStorage StorageConnection `json:"object_storage"`
	Tools         []ToolCredential  `json:"tools"`
}

ConnectionInfo 는 스택 접속에 필요한 정보 일체다.

type DeploymentState

type DeploymentState string

DeploymentState represents the state of a stack deployment.

const (
	StatePending     DeploymentState = "pending"
	StateValidating  DeploymentState = "validating"
	StateInstalling  DeploymentState = "installing"
	StateConfiguring DeploymentState = "configuring"
	StateHealthCheck DeploymentState = "health_check"
	StateCompleted   DeploymentState = "completed"
	StateCancelled   DeploymentState = "cancelled" //nolint:misspell // must match DB enum value
	StateFailed      DeploymentState = "failed"
	StateRollingBack DeploymentState = "rolling_back"
	StateRolledBack  DeploymentState = "rolled_back"
)

type GatewayBackend

type GatewayBackend struct {
	Service string
	Port    int
}

GatewayBackend 는 도구 호스트가 가리켜야 할 클러스터 안 서비스다.

func GatewayBackendForServiceAlias

func GatewayBackendForServiceAlias(service string) (GatewayBackend, bool)

GatewayBackendForServiceAlias 는 마법사가 지어낸 이름을 실제 백엔드로 옮긴다.

마법사는 모르는 도구를 "<도구>-svc" 로 만든다. 그 이름에서 도구를 되짚어 올바른 서비스와 포트를 찾는다.

func GatewayBackendForTool

func GatewayBackendForTool(tool string) (GatewayBackend, bool)

GatewayBackendForTool 은 도구 이름으로 백엔드를 찾는다.

이름 표기는 카탈로그·설정·매니페스트마다 흔들린다("Argo CD" / "argo-cd" / "argocd"). 정규화한 뒤에 본다.

type HelmStepMetadata

type HelmStepMetadata struct {
	StepName    string    `json:"step_name"`
	ReleaseName string    `json:"release_name,omitempty"`
	ChartName   string    `json:"chart_name"`
	RepoURL     string    `json:"repo_url,omitempty"`
	Version     string    `json:"version,omitempty"`
	Namespace   string    `json:"namespace,omitempty"`
	Phase       string    `json:"phase,omitempty"`
	SortOrder   int       `json:"sort_order"`
	Wait        bool      `json:"wait"`
	IsEnabled   bool      `json:"is_enabled"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

HelmStepMetadata stores the DB-backed Helm chart configuration for a stack step.

type KubernetesCompat

type KubernetesCompat struct {
	Min         string
	Max         string
	Recommended string
}

KubernetesCompat describes the Kubernetes version range supported by the matrix.

type LoggingConfig

type LoggingConfig struct {
	Collection ToolSelection `json:"collection"`
	Search     ToolSelection `json:"search"`
	TraceLayer ToolSelection `json:"trace_layer,omitempty"`
	// TraceExporter 는 애플리케이션이 보낸 텔레메트리를 받아 각 백엔드로
	// 흘려보내는 수집기다 (OpenTelemetry Collector).
	//
	// TraceLayer 와 칸을 따로 두는 이유는 역할이 다르기 때문이다 — TraceLayer 는
	// 추적을 저장·조회하는 백엔드(Tempo/Jaeger)이고, 이쪽은 그 앞에 서서 OTLP 를
	// 받아 추적·메트릭·로그를 각각의 저장소로 나눠 보낸다. 한 칸에 묶으면 둘 중
	// 하나만 설치할 수 있어 "수집기를 통해 관측한다"는 구성 자체가 불가능해진다.
	//
	// 프론트는 이전부터 이 값을 배포 요청에 실어 보냈으나 여기에 받는 칸이 없어
	// 조용히 버려졌다 — 설치 마법사의 Exporter/Agent 선택이 아무 일도 하지 않았다.
	TraceExporter ToolSelection `json:"trace_exporter,omitempty"`
}

LoggingConfig holds tool selections for the logging step.

type MonitoringConfig

type MonitoringConfig struct {
	Collection    ToolSelection `json:"collection"`
	Visualization ToolSelection `json:"visualization"`
}

MonitoringConfig holds tool selections for the monitoring step.

type PipelineConfig

type PipelineConfig struct {
	CIPlatform ToolSelection `json:"ci_platform"`
	CDTool     ToolSelection `json:"cd_tool"`
}

PipelineConfig holds tool selections for the pipeline step.

type PlanningOptionDef

type PlanningOptionDef struct {
	Key      string
	Baseline float64
	Min      float64
	Max      float64
	Weight   float64
	Impact   ResourceImpact
}

PlanningOptionDef 는 계획 행 하나가 묻는 질문이다 (예: "동시 러너 수").

type PlanningRowUnit

type PlanningRowUnit struct {
	Memory  string `json:"memory"`
	Storage string `json:"storage"`
}

PlanningRowUnit preserves display units chosen in the installer.

type ProtectedValueKind

type ProtectedValueKind string

ProtectedValueKind 는 보호 경로가 어떻게 훼손됐는지 구분한다.

const (
	// ProtectedValueRemoved 는 플랫폼이 넣어 둔 경로가 편집본에서 사라진 경우다.
	ProtectedValueRemoved ProtectedValueKind = "removed"
	// ProtectedValueChanged 는 값이 다른 것으로 바뀐 경우다.
	ProtectedValueChanged ProtectedValueKind = "changed"
)

type ProtectedValueViolation

type ProtectedValueViolation struct {
	Path    string             `json:"path"`
	Kind    ProtectedValueKind `json:"kind"`
	Message string             `json:"message"`
}

ProtectedValueViolation 은 편집본이 플랫폼 소유 경로를 훼손한 한 건이다.

func ProtectedValueViolations

func ProtectedValueViolations(step string, base, edited map[string]any) []ProtectedValueViolation

ProtectedValueViolations 는 편집본(edited)이 현재 배포값(base)의 보호 경로를 지웠거나 바꿨는지 검사한다.

base 에 없던 경로를 편집본이 새로 채우는 것은 위반이 아니다. 플랫폼이 아직 그 값을 세팅하지 않은 구성(예: access_domain 미설정)에서 사용자가 직접 지정하는 정상 경로이기 때문이다.

type ResourceDefault

type ResourceDefault struct {
	ToolKey          string    `json:"tool_key"`
	DisplayName      string    `json:"display_name"`
	CPURequest       float64   `json:"cpu_request"`
	CPULimit         float64   `json:"cpu_limit"`
	MemoryRequestGi  float64   `json:"memory_request_gi"`
	MemoryLimitGi    float64   `json:"memory_limit_gi"`
	StorageRequestGi float64   `json:"storage_request_gi"`
	StorageLimitGi   float64   `json:"storage_limit_gi"`
	IsDefault        bool      `json:"is_default"`
	UpdatedAt        time.Time `json:"updated_at"`
}

type ResourceEstimate

type ResourceEstimate struct {
	CPUCores       float64 `json:"cpu_cores"`
	MemoryGi       float64 `json:"memory_gi"`
	StorageGi      float64 `json:"storage_gi"`
	MonthlyCostUSD float64 `json:"monthly_cost_usd"`
}

ResourceEstimate holds computed resource requirements.

type ResourceImpact

type ResourceImpact struct {
	CPU     float64
	Memory  float64
	Storage float64
}

ResourceImpact 는 옵션 하나가 각 자원에 미치는 영향도다. 음수면 값이 커질수록 부하가 준다 (스크랩 주기처럼).

type ResourceMultipliers

type ResourceMultipliers struct {
	CPU     float64
	Memory  float64
	Storage float64

	RawCPU     float64
	RawMemory  float64
	RawStorage float64

	ClampedCPU     bool
	ClampedMemory  bool
	ClampedStorage bool
}

ResourceMultipliers 는 기준 벡터에 곱할 배수다. Clamped* 는 상·하한에 걸려 잘렸는지를 알린다 — 잘린 값을 그대로 보여주면 계획이 반영된 것처럼 읽힌다.

func PlanningMultipliers

func PlanningMultipliers(profile, slot string, optionValues map[string]float64) ResourceMultipliers

PlanningMultipliers 는 프로파일과 옵션값으로 기준 벡터에 곱할 배수를 낸다.

type ResourceVector

type ResourceVector struct {
	CPURequest       float64 `json:"cpuRequest"`
	CPULimit         float64 `json:"cpuLimit"`
	MemoryRequestGi  float64 `json:"memoryRequestGi"`
	MemoryLimitGi    float64 `json:"memoryLimitGi"`
	StorageRequestGi float64 `json:"storageRequestGi"`
	StorageLimitGi   float64 `json:"storageLimitGi"`
}

ResourceVector captures per-OSS applied request/limit values.

func ApplyPlanningMultipliers

func ApplyPlanningMultipliers(base ResourceVector, m ResourceMultipliers) ResourceVector

ApplyPlanningMultipliers 는 기준 벡터에 배수를 곱해 0.5 단위로 정리한다.

func PlanResourceVector

func PlanResourceVector(profile, slot string, base ResourceVector) ResourceVector

PlanResourceVector 는 프로파일 기본 옵션으로 계획한 최종 벡터다. 헤드리스 설치가 쓰는 진입점.

type ResourcesConfig

type ResourcesConfig struct {
	DevCount          int              `json:"developers"`
	ConcurrentRunners int              `json:"concurrent_runners"`
	CommitsPerWeek    int              `json:"weekly_commits"`
	BuildFrequency    string           `json:"build_frequency"` // low/medium/high or hourly/daily/on-push
	Calculated        ResourceEstimate `json:"calculated,omitempty"`
}

ResourcesConfig holds workload parameters and the calculated estimate.

type SourceControlConfig

type SourceControlConfig struct {
	// Owner 는 리포지토리가 만들어질 GitHub Organization 또는 사용자 계정이다.
	Owner string `json:"owner,omitempty"`
	// APIBaseURL 은 GitHub Enterprise Server 의 API 주소다.
	// 비면 github.com 을 쓴다.
	APIBaseURL string `json:"api_base_url,omitempty"`
}

SourceControlConfig 는 클러스터 밖 소스 저장소에 붙기 위한 설정이다.

GitHub 처럼 우리가 설치하지 않는 SCM 을 고른 스택에서만 채워진다. 주소도 소유자도 우리가 정할 수 없으므로 설치 마법사에서 받아 둔다.

자격증명(PAT)은 여기 없다 — 배포 요청 본문으로만 흐르고 OpenBao 로 바로 들어간다. 이 구조는 stacks.config JSONB 로 평문 저장되므로 토큰을 넣으면 DB 를 읽을 수 있는 누구에게나 노출된다.

type Stack

type Stack struct {
	ID                string          `json:"id"`
	Name              string          `json:"name"`
	TemplateID        string          `json:"template_id"`
	OrgID             string          `json:"org_id"`
	ClusterID         string          `json:"cluster_id"`
	Namespace         string          `json:"namespace"`
	Tools             []ToolConfig    `json:"tools,omitempty"`
	State             DeploymentState `json:"state"`
	Config            interface{}     `json:"config"` // JSONB
	CurrentStep       string          `json:"current_step,omitempty"`
	LastCompletedStep string          `json:"last_completed_step,omitempty"`
	LastFailedStep    string          `json:"last_failed_step,omitempty"`
	LastFailureReason string          `json:"last_failure_reason,omitempty"`
	CreatedAt         time.Time       `json:"created_at"`
	UpdatedAt         time.Time       `json:"updated_at"`
	DeletedAt         *time.Time      `json:"deleted_at,omitempty"`
}

Stack represents a deployed stack of DevOps tools.

func (*Stack) AddTools

func (s *Stack) AddTools(newTools []ToolConfig) error

func (*Stack) TransitionTo

func (s *Stack) TransitionTo(newState DeploymentState) error

TransitionTo attempts to transition the stack to a new state. Returns an error if the transition is not valid.

type StackConfig

type StackConfig struct {
	AccessDomain             string                        `json:"access_domain,omitempty"`
	AccessDomainTLS          *AccessDomainTLSConfig        `json:"access_domain_tls,omitempty"`
	Authentication           *AuthenticationConfig         `json:"authentication,omitempty"`
	YAMLOverrides            map[string]string             `json:"yaml_overrides,omitempty"`
	Artifacts                ArtifactsConfig               `json:"artifacts"`
	Pipeline                 PipelineConfig                `json:"pipeline"`
	Monitoring               MonitoringConfig              `json:"monitoring"`
	Logging                  LoggingConfig                 `json:"logging"`
	Resources                ResourcesConfig               `json:"resources"`
	OptionOverrides          map[string]map[string]float64 `json:"option_overrides,omitempty"`
	AppliedResourceOverrides map[string]ResourceVector     `json:"applied_resource_overrides,omitempty"`
	RowUnits                 map[string]PlanningRowUnit    `json:"row_units,omitempty"`
	Storage                  *StorageConfig                `json:"storage,omitempty"`
	SourceControl            *SourceControlConfig          `json:"source_control,omitempty"`
}

StackConfig holds the full configuration for a DevSecOps stack.

func DecodeStackConfig

func DecodeStackConfig(raw any) StackConfig

DecodeStackConfig 는 Stack.Config 에 실려오는 값을 StackConfig 로 되돌린다. 저장소에서 읽으면 JSONB 라 map 으로, 메모리에서 오면 구조체로 들어온다. 해석에 실패하면 빈 설정으로 떨어뜨린다 — 모니터링은 최선 노력 경로다.

type StackVersion

type StackVersion struct {
	ID           string
	StackID      string
	Version      int
	Config       StackConfig
	ChangedBy    string
	ChangeReason string
	CreatedAt    time.Time
}

StackVersion is a point-in-time snapshot of a stack's configuration.

type StorageConfig

type StorageConfig struct {
	PlanMode      string        `json:"plan_mode"`
	Database      StorageTarget `json:"database"`
	ObjectStorage StorageTarget `json:"object_storage"`
	// StorageClass is the Kubernetes StorageClass used by every PVC the stack
	// creates. Empty means "use the cluster default StorageClass"; installs on
	// clusters without a default SC must set it explicitly or PVCs stay Pending.
	StorageClass string `json:"storage_class,omitempty"`
}

type StorageConnection

type StorageConnection struct {
	Mode     string `json:"mode"`
	Engine   string `json:"engine"`
	Endpoint string `json:"endpoint"`
	// ResourceName 은 데이터베이스명 또는 버킷명이다.
	ResourceName string `json:"resource_name"`
	AuthID       string `json:"auth_id"`
	// SecretRef / SecretKey 는 비밀번호가 담긴 Secret 과 그 키다.
	SecretRef string `json:"secret_ref,omitempty"`
	SecretKey string `json:"secret_key,omitempty"`
}

StorageConnection 은 스토리지 접속 정보다.

type StorageTarget

type StorageTarget struct {
	Mode             string  `json:"mode"`
	ExistingRef      string  `json:"existing_ref,omitempty"`
	Endpoint         string  `json:"endpoint,omitempty"`
	ResourceName     string  `json:"resource_name,omitempty"`
	AccessSecretRef  string  `json:"access_secret_ref,omitempty"`
	AuthID           string  `json:"auth_id,omitempty"`
	AuthPasswordKey  string  `json:"auth_password_key,omitempty"`
	ProviderOrEngine string  `json:"provider_or_engine,omitempty"`
	Version          string  `json:"version,omitempty"`
	Size             float64 `json:"size,omitempty"`
}

type Template

type Template struct {
	ID                   string        `json:"id"`
	Name                 string        `json:"name"`
	Description          string        `json:"description"`
	Tools                []ToolConfig  `json:"tools"`
	EstimatedInstallTime time.Duration `json:"estimated_install_time"`
	RecommendedUseCase   string        `json:"recommended_use_case"`
	MinResources         string        `json:"min_resources"`
	PlanningProfile      string        `json:"planning_profile,omitempty"`
	CreatedBy            string        `json:"created_by,omitempty"`
}

Template represents a Golden Path template for stack deployment.

type ToolConfig

type ToolConfig struct {
	Category    string `json:"category"`
	Name        string `json:"name"`
	HelmVersion string `json:"helm_version"`
	AppVersion  string `json:"app_version"`
	Tool        string `json:"tool,omitempty"`
	Version     string `json:"version,omitempty"`
}

ToolConfig describes a tool included in a template.

type ToolCredential

type ToolCredential struct {
	Name      string `json:"name"`
	Username  string `json:"username,omitempty"`
	SecretRef string `json:"secret_ref,omitempty"`
	SecretKey string `json:"secret_key,omitempty"`
	Note      string `json:"note,omitempty"`
}

ToolCredential 은 OSS 도구 하나의 접속 안내다.

SecretRef 가 비어 있으면 조회할 Secret 이 없다는 뜻이고, 그때는 Note 가 무엇을 해야 하는지 설명한다. 값을 모를 때 그럴듯한 명령을 지어내지 않는다.

type ToolSelection

type ToolSelection struct {
	Name    string `json:"name"`
	Version string `json:"version"`
	Enabled bool   `json:"enabled"`
}

ToolSelection identifies a chosen tool by name and version.

func (*ToolSelection) UnmarshalJSON

func (t *ToolSelection) UnmarshalJSON(data []byte) error

type ToolVersion

type ToolVersion struct {
	Name          string
	HelmVersion   string
	AppVersion    string
	MinK8sVersion string
	ArchSupport   []string
	Tier          string
}

ToolVersion describes a single tool entry in a compatibility matrix.

MinK8sVersion, ArchSupport, Tier were introduced in migration 000041_compat_tool_fields to support the Pre-Deploy Gate (F8 v2).

  • MinK8sVersion: the minimum Kubernetes version the tool requires. Empty string means "inherit from matrix.Kubernetes.Min".
  • ArchSupport: the CPU architectures the tool ships images for (e.g. []string{"amd64", "arm64"}). Used by the ARM64 discovery check in the deploy wizard.
  • Tier: the maturity of this specific tool pairing inside the matrix. Distinct from CompatibilityMatrix.Status which is a matrix-level verdict.

func (ToolVersion) EffectiveMinK8sVersion

func (t ToolVersion) EffectiveMinK8sVersion(matrix KubernetesCompat) string

EffectiveMinK8sVersion returns MinK8sVersion if set, otherwise the matrix-level k8s.Min. Callers should use this when comparing against a target cluster version so that v1 matrices without per-tool data still answer correctly.

func (ToolVersion) SupportsArch

func (t ToolVersion) SupportsArch(arch string) bool

SupportsArch reports whether the tool lists the given CPU architecture as supported. An empty ArchSupport slice is treated as "amd64 only" for backward compatibility with v1 matrices that predate the field.

type ToolWorkload

type ToolWorkload struct {
	Key          string
	Name         string
	Version      string
	NamePrefixes []string
}

ToolWorkload 는 스택 설정이 클러스터에 실제로 띄우는 OSS 하나를 가리킨다.

NamePrefixes 는 그 OSS 가 만드는 파드·워크로드 이름의 접두사다. 릴리스명이 곧 이름 접두사가 되므로 설치 경로가 쓰는 릴리스 상수와 같은 값을 쓴다.

func InstalledToolWorkloads

func InstalledToolWorkloads(cfg StackConfig) []ToolWorkload

InstalledToolWorkloads 는 스택 설정에서 "이 스택이 클러스터에 설치하는 OSS" 목록을 뽑는다. 모니터링이 무엇을 보여줄지 정하는 단일 기준점이다 — 스택 상세 화면과 플랫폼 대시보드가 같은 답을 보게 하려면 양쪽 다 이 함수를 거쳐야 한다.

여기에 없는 OSS 는 파드가 멀쩡히 떠 있어도 어느 화면에도 나오지 않는다.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL