Documentation
¶
Index ¶
- Constants
- Variables
- func AllHelmReleaseNames() []string
- func BundleFixesFound(bundle *UpgradeBundle, present map[string]bool) []string
- func DefaultPlanningOptions(profile, slot string) map[string]float64
- func DefaultStackNamespaceFor(stackName string) string
- func GatewayPinnedHostnames(accessDomain string) []string
- func GitLabRunnerHelperImage(nodeArchs []string, version string) (string, bool)
- func HasImageScanner(sel ToolSelection) bool
- func HasSAST(sel ToolSelection) bool
- func HasSCA(sel ToolSelection) bool
- func HasTrivyServer(cfg StackConfig) bool
- func HelmReleaseNamesInUninstallOrder() []string
- func InstallMarkerValuePath(releaseName string) ([]string, bool)
- func IsGatewayCRD(name string) bool
- func IsInFlight(state DeploymentState) bool
- func IsNullusInstalledRelease(releaseName string, values map[string]any) bool
- func IsStaleInstall(state DeploymentState, updatedAt, now time.Time) bool
- func NormalizePlanningProfile(profile string) string
- func OTelCollectorOTLPGRPCEndpoint(namespace string) string
- func OTelCollectorOTLPHTTPEndpoint(namespace string) string
- func OTelCollectorServiceName() string
- func PlanAppliedResources(profile string, cfg StackConfig, baseByToolKey map[string]ResourceVector) map[string]ResourceVector
- func PlanningSlots() []string
- func ProfileAdjustedBaseline(profile string, def PlanningOptionDef) float64
- func ProfileFactorByOption(profile, optionKey string) float64
- func ProtectedValuePaths(step string) []string
- func RepinArgoCDHostAliases(values map[string]any, hostnames []string, ip string) (bool, []string)
- func RepinRunnerHostAliases(values map[string]any, hostnames []string, ip string) (bool, []string)
- func ResourceToolKey(name string) string
- func StackProgress(state DeploymentState, currentStep, lastCompletedStep string) (progress, ceiling int)
- func StepProgress(step string) int
- func StepProgressCeiling(step string) int
- func ToolAccessURL(toolName, accessDomain string) string
- func UpgradeChecksBlocked(checks []UpgradeCheck) bool
- func UpgradeToolSupported(tool string) bool
- func ValidateAccessDomain(accessDomain string) error
- type AccessDomainTLSConfig
- type ArchImageSource
- type ArtifactsConfig
- type AuthenticationConfig
- type CVEFinding
- type CompatibilityMatrix
- type ConfigDiff
- type ConnectionInfo
- type DeploymentState
- type GatewayBackend
- type HelmStepMetadata
- type ImageScanSkipReason
- type ImageScanState
- type ImageScanStatus
- type ImageSourceResolution
- type KubernetesCompat
- type LoggingConfig
- type MonitoringConfig
- type NewUpgradeBundleInput
- type NewUpgradeRunInput
- type ObjectStorageBackend
- type OrgStackImageScan
- type PipelineConfig
- type PlanningOptionDef
- type PlanningRowUnit
- type ProtectedValueKind
- type ProtectedValueViolation
- type ResourceDefault
- type ResourceEstimate
- type ResourceImpact
- type ResourceMultipliers
- type ResourceVector
- type ResourcesConfig
- type SecurityConfig
- type SharedComponent
- type SourceControlConfig
- type Stack
- type StackConfig
- type StackImageScan
- type StackImageScanReport
- type StackImageVulnerabilities
- type StackVersion
- type StorageConfig
- type StorageConnection
- type StorageTarget
- type Template
- type ToolConfig
- type ToolCredential
- type ToolImageProfile
- type ToolSelection
- type ToolVersion
- type ToolWorkload
- type UpgradeBundle
- type UpgradeCandidate
- type UpgradeCheck
- type UpgradeRun
- func (r *UpgradeRun) Active() bool
- func (r *UpgradeRun) BeginRollback(cause error, now time.Time)
- func (r *UpgradeRun) EnterHealthCheck(revision int, now time.Time)
- func (r *UpgradeRun) Fail(cause error, now time.Time)
- func (r *UpgradeRun) Interrupt(now time.Time)
- func (r *UpgradeRun) RequireManualIntervention(cause error, now time.Time)
- func (r *UpgradeRun) RolledBack(now time.Time)
- func (r *UpgradeRun) Stale(now time.Time) bool
- func (r *UpgradeRun) Succeed(now time.Time)
- func (r *UpgradeRun) Terminal() bool
Constants ¶
const ( HarborMultiArchImageRegistry = "ghcr.io/dasomel/goharbor" HarborMultiArchImageTag = "v2.15.0-build.32" HarborMultiArchImageReference = "https://github.com/dasomel/harbor" )
Harbor 멀티아키 재빌드 이미지.
공식 goharbor 이미지는 어느 버전도 arm64 를 내지 않는다(단일 아키 amd64 매니페스트). arm64 노드에서는 `fatal error: lfstack.push` 로 크래시해, DGX Spark 에서 스택 설치가 installing_harbor 에서 멈췄다(cloud-nullus/nullus#270).
dasomel/harbor 는 goharbor 를 매일 동기화해 amd64·arm64 로 다시 빌드하는 fork 다. 이미지는 cosign 으로 서명되고 SBOM·SLSA 증적이 붙는다. v2.15.x 빌드만 내므로 차트 1.15.0(앱 2.11.0) 위에서 앱 버전이 앞선다 — 에어갭 kind(Apple Silicon) 경로가 2026-05 부터 써 온 조합이고, 차트 1.15.0 과 앱 2.15.0 의 차트(1.19.0) 템플릿 차이는 프로브 값 템플릿화·namespace 명시·redis TLS 옵션 정도다.
태그는 에어갭 번들 목록(airgap/images/images.txt)과 같아야 한다. `v2.15.0` 은 재빌드마다 옮겨 가는 태그라 빌드 번호가 붙은 쪽을 쓴다.
const ( ToolTierStable = "stable" ToolTierBeta = "beta" ToolTierDeprecated = "deprecated" )
Tool tier constants describe the per-tool maturity level inside a matrix.
const ( ArchAMD64 = "amd64" ArchARM64 = "arm64" )
Node architecture constants used for per-tool ArchSupport.
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 를 내던 사고가 있었다.
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 기본값 // HarborSecretKeyKey 는 Harbor 가 **DB 에 저장하는 자격증명을 암호화할 때** // 쓰는 키다. 로봇 계정과 레플리케이션 엔드포인트 비밀번호가 이것으로 잠긴다. // // 차트 기본값은 `not-a-secure-key` 라는 공개 문자열이다. 그대로 두면 // Harbor DB 를 손에 넣은 사람이 차트에 적힌 키로 전부 풀 수 있다 — // 우리 백업 산출물(volumes/harbor-database)이 곧 평문이 된다는 뜻이다. // // 키 이름은 차트가 정한다(existingSecretSecretKey 가 가리키는 Secret 안에서 // `secretKey` 를 찾는다). 임의로 바꿀 수 없다. HarborSecretKeyKey = "secretKey" // #nosec G101 -- Secret 안의 키 이름 // HarborSecretKeyLength 는 Harbor 가 요구하는 길이다. AES-128 키라 // **정확히** 16자여야 하며, 다르면 core 가 기동 시 죽는다. HarborSecretKeyLength = 16 // TrivyReleaseName 은 이미지 취약점 스캐너 릴리스명이다. // // server 모드로 선다 — 취약점 DB 를 이 서버에만 두고, CI 잡은 client 로 // 붙어 패키지 목록만 보낸다. 클라이언트는 DB 를 내려받지 않으므로 // 에어갭 반입 지점이 파이프라인마다가 아니라 이 서버 하나로 줄어든다. // // 이름과 포트는 shared 가 소유한다 — cicd 가 CI 잡이 붙을 주소를 만들 때 // 같은 값을 봐야 하는데, 모듈끼리 서로의 internal 을 참조할 수 없다. TrivyReleaseName = shareddomain.TrivyReleaseName TrivyServiceName = TrivyReleaseName // TrivyServicePort 는 client 가 CVE 매칭을 요청하는 포트다. // 차트 기본 service.port 와 같아야 한다. TrivyServicePort = shareddomain.TrivyServicePort // 호환성 매트릭스가 선언한 버전과 같아야 한다. 화면은 매트릭스 값을 // 보여주고 설치는 차트 스펙을 쓰므로, 갈라지면 안내와 실제가 어긋난다. // (고정: TestChartVersionsMatchCompatibilityMatrix) TrivyChartVersion = "0.26.0" TrivyAppVersion = "0.74.0" // SonarQubeReleaseName 은 소스 정적 분석(SAST) 서버 릴리스명이다. // // 차트 기본 이름은 <릴리스>-sonarqube 라 fullnameOverride 로 릴리스명과 같게 // 둔다 — Service·StatefulSet·PVC 이름이 모두 이 값이 된다. SonarQubeReleaseName = shareddomain.SonarQubeReleaseName SonarQubeServiceName = SonarQubeReleaseName // SonarQubeServicePort 는 화면과 웹 API 포트다. 차트 기본 service.externalPort 와 같다. SonarQubeServicePort = shareddomain.SonarQubeServicePort // SonarQubeSecret 은 DB 비밀번호·모니터링 패스코드·관리자 비밀번호를 담는다. // OpenBao 에서 만든 값을 ESO 가 이 이름으로 옮긴다. SonarQubeSecret = "nullus-sonarqube-credentials" // 키 이름은 차트 jdbcOverwrite.jdbcSecretPasswordKey · monitoringPasscodeSecretKey // 에 그대로 넘긴다. SonarQubeDBPasswordKey = "jdbc-password" SonarQubeMonitoringPasscodeKey = "monitoring-passcode" SonarQubeAdminPasswordKey = "admin-password" // SonarQubeAdminUser 는 차트가 처음 만드는 관리자다. 첫 비밀번호는 admin 이고 // 프로비저닝이 바로 바꾼다. SonarQubeAdminUser = "admin" // SonarQubeDatabase / SonarQubeDBUser 는 공유 PostgreSQL 안의 전용 자리다. // GitLab DB 와 테이블 이름(users·projects·issues)이 겹쳐 같은 DB 를 쓸 수 없다. SonarQubeDatabase = "sonarqube" SonarQubeDBUser = "sonarqube" // 차트 버전과 실제로 깔리는 Community 빌드 번호다. 차트의 appVersion(2026.5.2)은 // 유료 Server 판의 번호라 Community 를 고르면 깔리는 것과 다르다. // (고정: TestChartVersionsMatchCompatibilityMatrix) SonarQubeChartVersion = "2026.5.1002" SonarQubeAppVersion = "26.9.0.129388" // 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 주소가 된다.
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" // GitLab Runner 는 별도 차트다. 차트 0.72.0 이 러너 17.7.0 을 싣는다. // AppVersion 은 helper 이미지 태그에 그대로 들어가므로(gitlab-runner-helper: // arm64-v17.7.0) 차트를 올릴 때 함께 올려야 한다 — 어긋나면 그 태그가 없어 // helper 를 받지 못하고 모든 CI 잡이 멈춘다. GitLabRunnerChartVersion = "0.72.0" GitLabRunnerAppVersion = "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.3 로 요건을 만족한다. // (고정: TestJenkinsAppVersion_SatisfiesGiteaPluginMinimum) JenkinsChartVersion = "5.9.54" JenkinsAppVersion = "2.568.3" // JenkinsGiteaPluginMinAppVersion 은 gitea 플러그인이 요구하는 Jenkins 하한이다. JenkinsGiteaPluginMinAppVersion = "2.528.3" MinIOChartVersion = "5.4.0" MinIOAppVersion = "RELEASE.2024-12-18T13-15-44Z" // SeaweedFS 는 오브젝트 스토리지의 다른 구현체다(domain.SeaweedFSObjectStorage). // 앱 버전은 이미지 태그와 같다(shareddomain.SeaweedFSImage). SeaweedFSChartVersion = "4.48.0" SeaweedFSAppVersion = "4.48" 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 주석 참고.
const ( OTelCollectorReleaseName = shareddomain.OTelCollectorReleaseName OTelAgentReleaseName = shareddomain.OTelAgentReleaseName OTelCollectorOTLPGRPCPort = shareddomain.OTelCollectorOTLPGRPCPort OTelCollectorOTLPHTTPPort = shareddomain.OTelCollectorOTLPHTTPPort )
OpenTelemetry 수집기의 이름·주소 규칙은 shared 가 소유한다.
cicd 는 배포하는 앱에 이 주소를 넣어 줘야 하는데, 모듈끼리 서로의 internal 을 참조할 수 없어 규칙을 shared 에 두고 양쪽이 같은 것을 본다. 여기서는 stack 코드가 계속 domain 이름으로 쓰도록 별칭만 남긴다.
const ( ArgoCDAdminSecret = "argocd-initial-admin-secret" // #nosec G101 -- Secret 리소스 이름 ArgoCDAdminUser = "admin" ArgoCDAdminPassKey = "password" // GitLabRootSecret 은 설치가 금고 값(artifacts/gitlab/root-password)으로 ESO 프로비저닝하는 // Secret 이다. 차트의 global.initialRootPassword 가 이것을 참조하므로 실제 root 비밀번호다. // 차트가 스스로 만드는 gitlab-gitlab-initial-root-password 는 참조하지 않는다 — 참조하지 않으면 // 차트가 임의 비밀번호를 거기 만들어, 금고·연결 정보·백업이 전부 가짜를 가리켰다(2026-10-12 실측). // 이 변경 전에 설치한 스택은 차트가 만든 그 Secret 이 실제 비밀번호다. GitLabRootSecret = "gitlab-initial-root-password" // #nosec G101 -- Secret 리소스 이름 GitLabRootUser = "root" GitLabRootPassKey = "password" GrafanaAdminUser = "admin" OpenSearchAdminUser = "admin" )
OSS 도구의 초기 자격증명이 담기는 Secret.
차트마다 이름 규칙이 다르다 — Argo CD 는 Deployment/Service 에는 릴리스 접두사를 붙이지만 Secret 에는 붙이지 않는다.
const ( // ObjectStorageAccessKey 는 스택이 쓰는 S3 액세스 키(사용자명)다. 비밀이 아니다. // MinIO 시절의 root 사용자명과 같은 값이라, 기존 스택의 자격이 그대로 이어진다. ObjectStorageAccessKey = MinIORootUser // ObjectStorageRegion 은 서명(SigV4)에 넣는 리전이다. 자체 호스팅 구현체는 // 리전을 따지지 않지만 서명 계산에는 들어가므로 소비자 모두가 같은 값을 써야 한다. ObjectStorageRegion = "us-east-1" ObjectStorageToolMinIO = "minio" ObjectStorageToolSeaweedFS = "seaweedfs" )
const ( SeaweedFSReleaseName = shareddomain.SeaweedFSReleaseName // SeaweedFSServiceName 은 all-in-one Service 다. 차트가 <fullname>-all-in-one 으로 // 짓고, 릴리스명에 차트 이름이 들어 있으면 fullname 이 릴리스명 그대로다. SeaweedFSServiceName = SeaweedFSReleaseName + "-all-in-one" // SeaweedFSS3Port 는 S3 게이트웨이 포트다. 차트 기본 s3.port 와 같다. SeaweedFSS3Port = 8333 // SeaweedFSMetricsPort 는 Prometheus 메트릭 포트다. 차트 기본 allInOne.metricsPort. SeaweedFSMetricsPort = 9324 // ProvisionedSeaweedFSSecret 은 S3 신원(identity) 설정을 담는다. ProvisionedSeaweedFSSecret = "nullus-seaweedfs-credentials" // #nosec G101 -- Secret 리소스 이름 SeaweedFSAccessKeyKey = "accessKey" SeaweedFSSecretKeyKey = "secretKey" // #nosec G101 -- Secret 안의 키 이름 // SeaweedFSS3ConfigKey 는 차트의 existingConfigSecret 이 찾는 키다. S3 게이트웨이가 // -s3.config 로 읽는 신원 JSON 이 들어 있다. SeaweedFSS3ConfigKey = "seaweedfs_s3_config" // SeaweedFSSFTPSecret 은 차트가 all-in-one 이면 SFTP 를 끄더라도 만드는 Secret 이다. // helm.sh/resource-policy: keep 이라 helm uninstall 이 남긴다 — 스택 삭제가 이름으로 지운다. SeaweedFSSFTPSecret = SeaweedFSReleaseName + "-sftp-secret" // #nosec G101 -- Secret 리소스 이름 // 버전(SeaweedFSChartVersion / SeaweedFSAppVersion)은 다른 도구처럼 connection.go 가 소유한다. SeaweedFSChartRepo = "https://seaweedfs.github.io/seaweedfs/helm" )
SeaweedFS 의 리소스 이름. Apache-2.0 이고 S3 게이트웨이를 내장한다.
차트의 all-in-one 모드로 세운다 — master·volume·filer·S3 게이트웨이가 파드 하나에 뜬다. 스택이 MinIO 를 standalone(단일 파드)으로 세우던 것과 같은 자리다.
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" SlotImageScanner = "security.imageScanner" SlotSAST = "security.sast" )
계획 슬롯. 도구 이름이 아니라 자리로 잇는다 — 이름은 gitlab / gitlab-ce 처럼 출처마다 흔들리지만 자리는 흔들리지 않는다.
const ( // LabelInstalledBy 는 Nullus 가 새로 설치한 공용 자원의 표시다. LabelInstalledBy = shareddomain.LabelInstalledBy InstalledByNullus = shareddomain.InstalledByNullus CertManagerReleaseName = "cert-manager" MetricsServerReleaseName = "metrics-server" // ESOReleaseName · ESONamespace 는 External Secrets 의 릴리스와 네임스페이스다. 설치(adapter/helm // 의 ESONamespace)와 같아야 한다 — 계약 테스트가 본다. ESOReleaseName = "external-secrets" ESONamespace = "external-secrets" // 내부 CA — 설치가 cert-manager 단계에서 만든다. 이름이 Nullus 전용이라 표시 없이도 // Nullus 것이다. 백업도 같은 이름으로 담는다(shared/domain). InternalCABootstrapIssuerName = shareddomain.InternalCABootstrapIssuerName InternalCAIssuerName = shareddomain.InternalCAIssuerName InternalCACertName = shareddomain.InternalCACertName InternalCASecretName = shareddomain.InternalCASecretName // EnvoyGatewayClassName 은 설치기가 만드는 GatewayClass 다. EnvoyGatewayClassName = shareddomain.EnvoyGatewayClassName EnvoyGatewayControllerName = shareddomain.EnvoyGatewayControllerName // CertManagerCRDSuffix 는 cert-manager CRD 의 API 그룹이다(acme.cert-manager.io 포함). CertManagerCRDSuffix = shareddomain.CertManagerCRDSuffix )
스택이 클러스터에 하나만 두고 함께 쓰는 공용 자원.
설치(adapter/helm)가 만들고 클러스터의 마지막 스택을 지울 때(usecase) 회수한다. 양쪽이 같은 이름과 같은 판별 규칙을 봐야 하므로 여기 둔다 — usecase 가 adapter 를 import 하면 레이어 방향이 뒤집힌다.
회수 원칙은 하나다. Nullus 가 설치한 것은 남기지 않고, Nullus 가 설치하지 않은 것은 건드리지 않는다. 설치는 클러스터에 이미 있는 cert-manager·metrics-server 를 재사용하므로 둘이 섞여 있을 수 있다 — 그것을 가르는 것이 설치 표시(LabelInstalledBy)다. 남기면 다음 설치를 막는다: 소유 표시가 남은 CRD 는 사용자가 다른 이름으로 cert-manager 를 설치할 때 Helm ownership 충돌을 낸다(ESO·Argo CD CRD 에서 겪은 것과 같다).
const ( PlanningProfileLocal = "local" PlanningProfileStartup = "startup" PlanningProfileStandard = "standard" PlanningProfileEnterprise = "enterprise" )
설치 규모 프로파일. 설치 마법사의 리소스 계획이 이 값에서 시작한다.
템플릿이 이 값을 들고 다니는 이유는, 도구 선택만으로는 스택이 몇 Gi 를 먹을지 정해지지 않기 때문이다 — 같은 Gitea+Jenkins+Argo CD 라도 standard 로 깔면 8Gi 노드에 들어가지 않는다. "무엇을 깔지"와 "얼마나 크게 깔지"는 함께 정해져야 한다.
const ( UpgradeBundleDraft = "draft" UpgradeBundleVerified = "verified" UpgradeBundleDeprecated = "deprecated" UpgradeBundleRevoked = "revoked" )
번들 상태. verified 만 후보가 되고 실행할 수 있다.
const ( UpgradeStatusBlocked = "blocked" UpgradeStatusUpgrading = "upgrading" UpgradeStatusFailed = "failed" UpgradeStatusSucceeded = "succeeded" UpgradeStatusRollingBack = "rolling_back" UpgradeStatusRolledBack = "rolled_back" UpgradeStatusManual = "manual_intervention_required" )
실행 상태. upgrading · rolling_back 은 진행 중이고, 나머지는 끝난 상태다. failed 는 Helm 이 릴리스를 건드리기 전에 실패한 것(아무것도 바뀌지 않음), rolled_back 은 바뀌었다가 출발 버전으로 돌아온 것이다.
const ( UpgradeStepPreflight = "preflight" UpgradeStepHelmUpgrade = "helm_upgrade" UpgradeStepHealthCheck = "health_check" UpgradeStepRollback = "rollback" UpgradeStepComplete = "complete" )
실행 단계.
const ( UpgradeCheckPass = "pass" UpgradeCheckWarning = "warning" UpgradeCheckBlocked = "blocked" )
사전 점검 결과.
const DefaultStackNamespace = shareddomain.DefaultStackNamespace
DefaultStackNamespace 는 스택 네임스페이스가 정해지지 않았을 때의 기본값이다. 설치 경로와 안내 경로가 같은 값을 봐야 하므로 domain 이 소유한다.
const GitLabRunnerHelperImageRepository = "registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper"
GitLab Runner 의 Kubernetes executor 는 잡마다 helper 컨테이너를 띄운다. 그 이미지 태그에는 아키텍처가 박혀 있고(gitlab-runner-helper:x86_64-v17.7.0), 설정하지 않으면 러너가 x86_64 를 고른다 — 러너 자신이 arm64 로 돌고 있어도 그렇다. arm64 노드에서는 helper 의 init 컨테이너가 실행되지 못해 그 스택의 모든 CI 잡이 runner_system_failure 로 끝난다.
이 실패는 설치로는 드러나지 않는다. 헬름은 성공하고 러너 파드도 Running 이며 스택은 completed 로 끝나고 Pre-Deploy Gate 도 통과한다 — 파이프라인을 실제로 돌려 봐야 드러난다. Harbor(#270)와 같은 부류이지만 그 게이트는 차트가 받는 컴포넌트 이미지만 보므로 러너 설정 안의 이 이미지는 잡지 못한다.
const KubePrometheusStackReleaseName = "kube-prometheus-stack"
KubePrometheusStackReleaseName 은 Prometheus·Alertmanager·Operator 릴리스다.
const MaxUpgradeIdempotencyKeyLength = 128
MaxUpgradeIdempotencyKeyLength 는 Idempotency-Key 의 최대 길이다(UUID 는 36자).
const PrometheusOperatorCRDsReleaseName = "prometheus-operator-crds"
PrometheusOperatorCRDsReleaseName 은 Prometheus Operator CRD(ServiceMonitor·Probe·PrometheusRule 등)만 담은 릴리스다. 이 CRD 를 쓰는 리소스가 다른 릴리스 여럿에 들어 있다.
const StaleInstallThreshold = 30 * time.Minute
StaleInstallThreshold 는 이만큼 아무 진전이 없으면 끊긴 것으로 본다.
한 스텝이 오래 걸릴 수 있다 — GitLab 은 helm --wait 타임아웃만 15분이다. 그 동안에는 행이 갱신되지 않으므로 여유를 크게 잡는다. 너무 짧게 잡으면 살아 있는 설치를 실패로 표시해 버린다.
const UpgradeHeartbeatTimeout = 5 * time.Minute
UpgradeHeartbeatTimeout 은 진행 중 실행의 심장 박동(updated_at)이 끊긴 채 버틸 수 있는 시간이다. 실행 중인 프로세스는 1분마다 박동을 남긴다 — Helm 호출 한 번이 훅 · 대기 · 되돌리기로 한 시간을 넘겨도 닫히지 않는다. 박동이 이보다 오래 없으면 API 가 작업 중에 죽은 것으로 보고 닫는다 — 그대로 두면 그 스택의 업그레이드가 영원히 막힌다.
const UpgradeToolArgoCD = "argocd"
Variables ¶
var ( ErrUpgradeReasonRequired = errors.New("업그레이드 사유가 필요하다") ErrUpgradeIdempotencyKeyRequired = errors.New("Idempotency-Key 가 필요하다") ErrUpgradeIdempotencyKeyInvalid = fmt.Errorf("Idempotency-Key 는 %d 자 이하여야 한다", MaxUpgradeIdempotencyKeyLength) // ErrUpgradeIdempotencyKeyReused 는 같은 키가 다른 번들의 실행에 이미 쓰였을 때다 — 재시도가 아니다. ErrUpgradeIdempotencyKeyReused = errors.New("이 Idempotency-Key 는 다른 업그레이드에 이미 쓰였다") // ErrUpgradeRunClosed 는 진행 중이 아닌 실행을 바꾸려 할 때다 — 다른 곳(중단 처리)이 이미 닫았다. ErrUpgradeRunClosed = errors.New("업그레이드 실행이 이미 끝났다") ErrUpgradeInProgress = errors.New("이 스택에서 다른 업그레이드가 진행 중이다") ErrUpgradeBundleNotFound = errors.New("검증된 업그레이드 번들이 없다") ErrUpgradeRunNotFound = errors.New("업그레이드 실행이 없다") ErrUpgradeReleaseNotFound = errors.New("업그레이드할 Helm 릴리스가 없다") )
var ( ErrUpgradeBundleInvalid = errors.New("업그레이드 번들이 올바르지 않다") // ErrUpgradeBundleUnknown 은 상태와 무관하게 그 ID 의 번들이 없을 때다. ErrUpgradeBundleNotFound // 는 "실행할 수 있는(verified) 번들이 없다" 는 뜻이라 관리 화면에는 맞지 않는다. ErrUpgradeBundleUnknown = errors.New("업그레이드 번들이 없다") ErrUpgradeBundleExists = errors.New("같은 ID 또는 같은 경로(도구 · 출발 · 대상)의 업그레이드 번들이 이미 있다") ErrUpgradeBundleRehearsalRequired = errors.New("verified 번들은 실클러스터 리허설을 마쳤다고 확인해야 한다") ErrUpgradeBundleStatusTransition = errors.New("허용되지 않는 번들 상태 변경이다") )
var InstallStepOrder = []string{
"installing_cert_manager",
"installing_prometheus_crds",
"installing_metrics_server",
"installing_openbao",
"installing_external_secrets",
"provisioning_secrets",
"installing_postgresql",
"installing_minio",
"installing_seaweedfs",
"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_trivy",
"installing_sonarqube",
"provisioning_sonarqube",
"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 으로 나왔다. 그러면 화면이 다른 근거로 값을 지어내고, 시크릿만 깔린 시점에 막대가 절반을 넘긴 것처럼 보였다.
순서는 오케스트레이터가 실제로 도는 순서와 같아야 한다 — 그쪽이 이 목록을 그대로 쓴다.
var InstalledHelmReleaseNames = []string{ "cert-manager", PrometheusOperatorCRDsReleaseName, "metrics-server", "openbao", "external-secrets", "nullus-postgresql", "nullus-minio", SeaweedFSReleaseName, HarborReleaseName, NexusReleaseName, "gitlab", GiteaReleaseName, "argo-cd", TrivyReleaseName, SonarQubeReleaseName, "gitlab-runner", JenkinsReleaseName, KubePrometheusStackReleaseName, "grafana", "loki", "opensearch", "elasticsearch", "opentelemetry-collector", "tempo", "jaeger", OTelCollectorReleaseName, OTelAgentReleaseName, "eg", }
InstalledHelmReleaseNames 는 스택 설치가 만들어 내는 모든 Helm 릴리스다. 로깅/트레이스처럼 설정에 따라 차트가 갈리는 단계는 가능한 변형을 모두 포함한다.
var LegacyHelmReleaseNames = []string{
"postgresql",
"minio",
"envoy-gateway",
}
LegacyHelmReleaseNames 는 과거 이름으로 설치된 스택을 지우기 위해 남겨 둔다. 설치 경로는 더 이상 이 이름을 쓰지 않는다.
var MinIOObjectStorage = ObjectStorageBackend{ Tool: ObjectStorageToolMinIO, DisplayName: "MinIO (SILO)", Step: "installing_minio", ReleaseName: MinIOServiceName, ServiceName: MinIOServiceName, ServicePort: MinIOServicePort, CredentialSecret: ProvisionedMinIOSecret, AccessKeyKey: MinIOUserKey, SecretKeyKey: MinIOPasswordKey, VaultAccessKeyPath: "artifacts/minio/root-user", VaultSecretKeyPath: "artifacts/minio/root-password", }
MinIOObjectStorage 는 MinIO(현재 이미지는 커뮤니티 포크 SILO)다.
이름·키·금고 경로는 이 표가 생기기 전 그대로다 — 이미 설치된 스택의 금고와 Secret 을 그대로 읽어야 하므로 바꾸지 않는다. 표시 이름만 포크를 함께 적는다 — 화면의 마크(silo.svg)가 SILO 라 "MinIO" 만 적으면 다른 제품처럼 읽힌다.
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}}, }, SlotImageScanner: { {Key: "scansPerDay", Baseline: 40, Min: 1, Max: 2000, Weight: 0.6, Impact: ResourceImpact{CPU: 1, Memory: 0.6, Storage: 0.1}}, {Key: "concurrentScans", Baseline: 2, Min: 1, Max: 50, Weight: 0.4, Impact: ResourceImpact{CPU: 0.9, Memory: 0.8, Storage: 0.1}}, }, SlotSAST: { {Key: "scansPerDay", Baseline: 40, Min: 1, Max: 2000, Weight: 0.6, Impact: ResourceImpact{CPU: 1, Memory: 0.5, Storage: 0.2}}, {Key: "projectCount", Baseline: 20, Min: 1, Max: 1000, Weight: 0.4, Impact: ResourceImpact{CPU: 0.3, Memory: 0.8, Storage: 0.6}}, }, }
PlanningOptionDefs 는 슬롯별 옵션 정의다.
var SeaweedFSObjectStorage = ObjectStorageBackend{ Tool: ObjectStorageToolSeaweedFS, DisplayName: "SeaweedFS", Step: "installing_seaweedfs", ReleaseName: SeaweedFSReleaseName, ServiceName: SeaweedFSServiceName, ServicePort: SeaweedFSS3Port, CredentialSecret: ProvisionedSeaweedFSSecret, AccessKeyKey: SeaweedFSAccessKeyKey, SecretKeyKey: SeaweedFSSecretKeyKey, VaultAccessKeyPath: "artifacts/seaweedfs/access-key", VaultSecretKeyPath: "artifacts/seaweedfs/secret-key", }
SeaweedFSObjectStorage 는 SeaweedFS 다.
Functions ¶
func AllHelmReleaseNames ¶
func AllHelmReleaseNames() []string
AllHelmReleaseNames 는 삭제가 훑어야 하는 릴리스 전체다.
func BundleFixesFound ¶ added in v0.6.0
func BundleFixesFound(bundle *UpgradeBundle, present map[string]bool) []string
BundleFixesFound 는 번들이 고치는 CVE 중 present(지금 스캔에서 발견된 것)에 있는 것이다. 정렬해 돌려준다.
func DefaultPlanningOptions ¶
DefaultPlanningOptions 는 사용자가 아무것도 만지지 않은 상태의 옵션값이다. 헤드리스 설치는 언제나 이 상태로 계획한다.
func DefaultStackNamespaceFor ¶
DefaultStackNamespaceFor 는 스택 이름에서 기본 네임스페이스를 만든다.
예전 기본값은 DefaultStackNamespace("nullus") 하나였고, 그것은 플랫폼 자신이 사는 네임스페이스와 같았다. 그래서 두 가지가 동시에 깨졌다 —
- 설치: 스택의 PostgreSQL 릴리스(nullus-postgresql)가 플랫폼 차트가 이미 소유한 같은 이름의 리소스와 부딪혀 Helm 이 거부한다.
- 삭제: 스택 정리가 같은 네임스페이스를 훑으며 플랫폼 리소스를 지운다. 2026-08-20 에 실제로 nullus.io 가 통째로 내려갔다.
스택마다 자기 네임스페이스를 갖게 하면 두 경로 모두 애초에 만나지 않는다.
func GatewayPinnedHostnames ¶ added in v0.6.0
GatewayPinnedHostnames 는 게이트웨이 주소를 박아 두는 스택 도구 이름이다. CI 잡은 스택 GitLab 에서 소스를 받고 스택 레지스트리에 이미지를 올린다. 접근 도메인이 없으면 박을 것도 없다.
func GitLabRunnerHelperImage ¶ added in v0.6.0
GitLabRunnerHelperImage 는 이 클러스터의 노드에서 뜨는 helper 이미지를 고른다.
노드 아키텍처가 한 종류일 때만 고른다. 섞여 있으면 태그 하나로 양쪽을 덮을 수 없고, 노드를 모르거나 처음 보는 아키텍처면 지금까지의 동작(러너 기본값)을 그대로 둔다 — 잘못 박으면 지금 도는 클러스터를 우리가 깨뜨린다.
func HasImageScanner ¶ added in v0.6.0
func HasImageScanner(sel ToolSelection) bool
HasImageScanner 는 스택 안에 이미지 스캐너를 세우는 선택인지 본다.
이름을 보지 않는다 — 스캐너 슬롯의 선택지는 현재 Trivy 하나뿐이고, 고른 사실 자체가 곧 설치 여부다. 외부(external) 선택은 스택 안에 서지 않는다.
func HasSAST ¶ added in v0.6.0
func HasSAST(sel ToolSelection) bool
HasSAST 는 스택 안에 정적 분석(SAST) 서버를 세우는 선택인지 본다.
이미지 스캐너와 같은 규칙이다 — 슬롯의 선택지는 SonarQube 하나뿐이라 고른 사실 자체가 곧 설치 여부이고, 외부(external) 선택은 스택 안에 서지 않는다.
func HasSCA ¶ added in v0.6.0
func HasSCA(sel ToolSelection) bool
HasSCA 는 스택 Trivy 서버로 의존성을 스캔하는 선택인지 본다. 외부(external) 선택은 스택 안에 서버를 세우지 않는다 — 이미지 스캐너·SAST 와 같은 판단이다.
func HasTrivyServer ¶ added in v0.6.0
func HasTrivyServer(cfg StackConfig) bool
HasTrivyServer 는 스택에 Trivy 서버를 세우는지 본다 — 이미지 스캐너나 의존성 스캔 중 하나라도 골랐으면 선다. 설치 단계(installing_trivy)·계획·모니터링 목록이 같은 답을 보도록 이 함수 하나를 쓴다.
func HelmReleaseNamesInUninstallOrder ¶ added in v0.6.0
func HelmReleaseNamesInUninstallOrder() []string
HelmReleaseNamesInUninstallOrder 는 삭제가 릴리스를 지우는 순서다.
CRD 만 담은 릴리스는 그 CRD 를 쓰는 릴리스를 다 지운 뒤에 지운다. helm uninstall 은 릴리스 매니페스트를 객체로 만든 다음 지우는데, 그 안의 ServiceMonitor·Probe 의 CRD 가 이미 없으면 객체를 만들지 못해 아무것도 지우지 않고 "failed to delete release" 로 멈춘다. 2026-10-12 실측 — CRD 릴리스가 두 번째로 지워지자 argo-cd·nullus-minio·kube-prometheus-stack·grafana 가 모두 그렇게 멈췄고, 네임스페이스 회수가 안쪽은 치웠지만 kube-system 의 Service 5개와 grafana ClusterRole 이 남아 다음 스택 설치가 installing_prometheus 에서 소유권 충돌로 실패했다.
설치 순서(InstalledHelmReleaseNames)는 그대로 둔다 — CRD 가 먼저 깔려야 하는 것은 설치 쪽 사정이다.
func InstallMarkerValuePath ¶ added in v0.6.0
InstallMarkerValuePath 는 릴리스의 설치 표시 자리다. ok=false 면 공용 릴리스가 아니다.
func IsGatewayCRD ¶ added in v0.6.0
IsGatewayCRD 는 게이트웨이 단계가 까는 CRD 인지 본다. 판별 규칙은 백업과 같아야 하므로 공용 도메인의 것이다.
func IsNullusInstalledRelease ¶ added in v0.6.0
IsNullusInstalledRelease 는 릴리스 values 를 보고 Nullus 가 설치한 공용 릴리스인지 판별한다.
설치 표시가 있으면 Nullus 것이다. 표시가 없으면 표시를 달기 전 Nullus 가 설치한 모양(지문)인지 본다 — 그 전에는 표시가 없었으므로 지문 없이는 옛 설치를 회수할 수 없다.
지문은 자원 수치가 아니라 구조로 본다. 수치는 관리자 기본값으로 바뀐다(kind-nullus-platform 의 webhook 은 DefaultValues 의 250m 가 아니라 500m 로 설치돼 있었다). 지문이 고객 설치와 우연히 겹쳐도, 삭제는 그 자원을 쓰는 곳이 있으면 남기므로 쓰던 것이 사라지지는 않는다.
func IsStaleInstall ¶
func IsStaleInstall(state DeploymentState, updatedAt, now time.Time) bool
IsStaleInstall 은 진행 중이라고 표시돼 있지만 실제로는 끊긴 설치인지 본다.
설치는 API 프로세스 안의 고루틴이 돌린다. 파드가 교체되면 그 고루틴이 사라지고, 아무도 실패를 기록하지 않는다 — 스택은 installing 인 채로 영원히 남는다. 그 상태에서는 이어서 진행(continue)도 막히므로(failed/pending 만 허용) 사용자에게는 지우고 다시 까는 길밖에 없다. 2026-08-20 운영에서 실제로 그렇게 갇혔다.
살아 있는 설치와 구분할 방법은 시간뿐이다. 여러 레플리카가 도는 환경에서는 "재시작했으니 죽었다" 고 단정할 수 없다.
func NormalizePlanningProfile ¶
NormalizePlanningProfile 은 공백·대소문자를 흡수하고, 빈 값을 기본 프로파일로 채운다. 아는 값이 아니면 빈 문자열을 돌려준다 — 오타를 조용히 standard 로 바꾸면 8Gi 를 노린 템플릿이 그 두 배로 설치되므로, 판단은 호출자에게 남긴다.
func OTelCollectorOTLPGRPCEndpoint ¶
OTelCollectorOTLPGRPCEndpoint 는 애플리케이션이 OTLP/gRPC 로 보낼 주소다.
func OTelCollectorOTLPHTTPEndpoint ¶
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 ProfileAdjustedBaseline ¶
func ProfileAdjustedBaseline(profile string, def PlanningOptionDef) float64
ProfileAdjustedBaseline 은 프로파일이 적용된 옵션 기본값이다. 마법사가 화면을 열 때 채워 넣는 값과 같다.
func ProfileFactorByOption ¶
ProfileFactorByOption 은 프로파일이 옵션 기본값을 몇 배로 조정하는지 돌려준다.
성격별로 방향이 다르다 — 보관 기간·처리량은 작은 프로파일에서 줄지만, 주기 (interval)는 늘어난다. 주기가 길수록 부하가 줄기 때문이다.
func ProtectedValuePaths ¶
ProtectedValuePaths 는 해당 설치 단계에서 플랫폼이 소유한 values 경로다. 모르는 단계는 빈 슬라이스를 돌려준다 — 보호할 것이 없다는 뜻이다.
func RepinArgoCDHostAliases ¶ added in v0.6.0
RepinArgoCDHostAliases 는 Argo CD values 의 global.hostAliases 중 스택 도구 항목의 ip 를 바꾼다. 바꿨는지와 바뀌기 전 주소들을 돌려준다. values 를 그 자리에서 고친다.
func RepinRunnerHostAliases ¶ added in v0.6.0
RepinRunnerHostAliases 는 러너 values 의 runners.config(TOML) 중 스택 도구 host_aliases 블록의 ip 를 바꾼다. 바꿨는지와 바뀌기 전 주소들을 돌려준다. values 를 그 자리에서 고친다.
func ResourceToolKey ¶
ResourceToolKey 는 도구 표기명을 자원 기본값 표의 키로 옮긴다.
func StackProgress ¶
func StackProgress(state DeploymentState, currentStep, lastCompletedStep string) (progress, ceiling int)
StackProgress 는 저장된 스택 상태만으로 진행률을 되살린다.
새로고침하면 WebSocket 이 처음부터 다시 붙어 그동안의 진행률을 모른다. 예전에는 화면이 상태(installing 등)를 뭉뚱그린 표로 대신 채웠는데, 그 값은 스텝 기반 진행률과 달라서 **새로고침할 때마다 퍼센트가 튀었다**. 같은 계산을 여기서 한 번 더 해 주면 두 경로가 같은 값을 본다.
진행 중인 스텝이 있으면 그 스텝의 값이다. 없으면 마지막으로 끝낸 스텝까지는 갔다는 뜻이므로 그 스텝의 상한을 쓴다.
func StepProgress ¶
StepProgress 는 그 스텝을 밟는 동안 보여 줄 진행률이다.
설치 스텝은 5~90 을 균등하게 나눠 갖는다. 스텝 하나가 끝나면 딱 그만큼 오른다 — 시간이 아니라 실제로 한 일에 맞춰 움직인다.
모르는 스텝은 -1 이다. 0 을 돌려주면 "아직 시작 전" 과 구분되지 않아, 화면이 진행률을 다른 근거로 지어내게 된다.
func StepProgressCeiling ¶
StepProgressCeiling 은 그 스텝이 끝났을 때 닿을 값이다.
화면은 이 값을 상한으로 삼아 스텝 안에서만 조금씩 움직인다 — 다음 스텝의 몫까지 미리 채우면 하지 않은 일을 한 것처럼 보여 준다.
func ToolAccessURL ¶
ToolAccessURL 은 스택 접속 도메인 위에 선 OSS 하나의 웹 주소다.
주소 규칙이 단일 출처여야 하는 이유는 화면이 여러 개이기 때문이다 — 스택 상세 화면, 모니터링 대시보드, 연결정보 안내가 모두 "Grafana 는 어디로 들어가는가"를 답해야 한다. 각자 조립하면 한 곳만 바뀌었을 때 조용히 갈라지고, 사용자는 화면마다 다른 주소를 본다.
스킴은 항상 https 다. 접속 도메인은 게이트웨이 TLS 리스너 뒤에 서고, 임베드 탭도 https 를 전제로 정규화한다 — 여기서 http 를 내려주면 브라우저가 혼합 콘텐츠로 막거나 리다이렉트 한 번을 더 타게 된다.
주소를 모르는 도구는 빈 문자열을 돌려준다. 그럴듯한 호스트를 지어내면 화면이 죽은 링크를 안내하게 되므로, 모를 때는 링크를 걸지 않는 편이 낫다.
func UpgradeChecksBlocked ¶ added in v0.6.0
func UpgradeChecksBlocked(checks []UpgradeCheck) bool
UpgradeChecksBlocked 는 하나라도 차단이면 참이다. 경고는 실행을 막지 않는다.
func UpgradeToolSupported ¶ added in v0.6.0
UpgradeToolSupported 는 그 도구의 업그레이드를 Nullus 가 실행할 수 있는지다.
func ValidateAccessDomain ¶
ValidateAccessDomain 은 접속 도메인이 실제로 라우팅·발급에 쓸 수 있는 값인지 본다.
이 값 하나가 스택의 모든 주소가 된다 — HTTPRoute 의 hostname("gitlab.<도메인>"), 게이트웨이 인증서의 commonName 과 dnsNames("*.<도메인>"), 도구들의 redirect_uri. 그래서 형식이 깨지면 설치는 끝나도 아무것도 열리지 않는다.
2026-08-20 운영 스택은 access_domain 이 ".io" 로 저장돼 있었다. 만들어진 매니페스트는 hostname "jenkins..io", 인증서 dnsNames "*..io" 였다. 아무도 막지 않아서 설치 절차를 다 태운 뒤에야 드러났다.
Types ¶
type AccessDomainTLSConfig ¶
type ArchImageSource ¶ added in v0.6.0
type ArchImageSource struct {
// Archs 는 이 출처의 이미지가 내는 아키텍처다. 한 벌의 이미지가 모든 노드에
// 깔리므로, 이 출처를 쓰려면 클러스터의 노드 아키텍처를 전부 덮어야 한다.
Archs []string
// Registry 는 컴포넌트 이미지 이름 앞에 붙는 저장소 경로다.
// 컴포넌트 이름(harbor-core 등)은 차트를 아는 설치 어댑터가 붙인다.
Registry string
Tag string
// Reference 는 이미지를 만드는 저장소다. 설치 로그에 출처로 남긴다.
Reference string
}
ArchImageSource 는 공식 이미지가 내지 않는 아키텍처를 채우는 대체 이미지 출처다.
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 CVEFinding ¶ added in v0.6.0
type CVEFinding struct {
ID string
// Packages 는 "패키지 설치버전 → 수정버전" 이다.
Packages []string
Images []string
// Exposed 는 그 CVE 가 든 이미지 중 하나라도 클러스터 밖에 열려 있는지다.
Exposed bool
Hosts []string
}
CVEFinding 은 알릴 취약점 하나다. 여러 이미지에 같은 CVE 가 있으면 하나로 묶는다.
func NewFixableCriticals ¶ added in v0.6.0
func NewFixableCriticals(known map[string]bool, scans []StackImageScan) []CVEFinding
NewFixableCriticals 는 known(지난 스캔에서 이미 본 것)에 없는 "수정판 있는 CRITICAL" 을 고른다. 외부에 노출된 것을 앞에, 같으면 ID 순으로 둔다. 목록이 기록되지 않은 이미지는 볼 수 없다.
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 ¶
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 ¶
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 ImageScanSkipReason ¶ added in v0.6.0
type ImageScanSkipReason string
ImageScanSkipReason 은 설치 이미지를 스캔하지 않는 이유다.
const ( ImageScanReasonScannerNotInstalled ImageScanSkipReason = "scanner_not_installed" // ImageScanReasonAirgap 은 에어갭 설치라 스캔하지 않던 때의 이유다. 이제 만들지 않지만, 화면이 옛 // 응답을 읽을 수 있게 남긴다. ImageScanReasonAirgap ImageScanSkipReason = "airgap" )
func ImageScanSkipReasonFor ¶ added in v0.6.0
func ImageScanSkipReasonFor(cfg StackConfig) ImageScanSkipReason
ImageScanSkipReasonFor 는 스택의 설치 이미지를 스캔하지 않는 이유다. 빈 값이면 스캔할 수 있다.
에어갭 설치도 스캔한다 — 이미지는 내부 레지스트리(번들이 올린 경로)에서 받고, 취약점 DB 는 번들이 반입한 것을 쓴다. DB 가 반입한 날짜에 멈춰 있으므로 보고서가 그것을 밝힌다(StackImageScanReport.Airgap).
type ImageScanState ¶ added in v0.6.0
type ImageScanState string
ImageScanState 는 스택 단위의 스캔 상태다.
const ( ImageScanStateScanned ImageScanState = "scanned" // ImageScanStatePending 은 스캐너가 있지만 아직 결과가 없다는 뜻이다. ImageScanStatePending ImageScanState = "pending" // ImageScanStateNotScanned 는 이 스택의 설치 이미지를 스캔하지 않는다는 뜻이다. ImageScanStateNotScanned ImageScanState = "not_scanned" )
type ImageScanStatus ¶ added in v0.6.0
type ImageScanStatus string
ImageScanStatus 는 이미지 하나의 스캔 결과 상태다.
const ( ImageScanStatusScanned ImageScanStatus = "scanned" // ImageScanStatusFailed 는 그 이미지를 스캔하지 못했다는 뜻이다. 건수를 모른다. ImageScanStatusFailed ImageScanStatus = "failed" )
type ImageSourceResolution ¶ added in v0.6.0
type ImageSourceResolution struct {
// Source 가 nil 이면 공식 이미지를 그대로 쓴다.
Source *ArchImageSource
// Unsupported 는 어느 이미지로도 뜰 수 없는 노드 아키텍처다.
Unsupported []string
}
ImageSourceResolution 은 노드 아키텍처에 맞춰 고른 이미지 출처다.
type KubernetesCompat ¶
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 NewUpgradeBundleInput ¶ added in v0.6.0
type NewUpgradeBundleInput struct {
// ID 를 비우면 <도구>-<출발 차트>-<대상 차트> 다.
ID string
Tool string
ReleaseName string
ChartName string
RepoURL string
SourceChartVersion string
SourceAppVersion string
TargetChartVersion string
TargetAppVersion string
RiskLevel string
ExpectedDisruption string
ReleaseNotes string
RequiresBackup bool
SupportedArchitectures []string
FixesCVEs []string
// Status 는 draft 또는 verified 다. 비우면 draft.
Status string
// RehearsalConfirmed 는 운영자가 "이 경로를 실클러스터에서 리허설했다" 고 확인한 것이다.
// verified 는 이것 없이 만들 수 없다.
RehearsalConfirmed bool
Now time.Time
}
type NewUpgradeRunInput ¶ added in v0.6.0
type NewUpgradeRunInput struct {
ID, StackID string
Bundle UpgradeBundle
SourceChartVersion string
PreviousRevision int
RequestedBy string
Reason string
IdempotencyKey string
Checks []UpgradeCheck
Now time.Time
}
type ObjectStorageBackend ¶ added in v0.6.0
type ObjectStorageBackend struct {
// Tool 은 카탈로그 이름을 정규화한 값이다. storage_backend 선택과 맞춰 본다.
Tool string
// DisplayName 은 화면·로그에 쓰는 이름이다.
DisplayName string
// Step 은 이 구현체를 세우는 설치 단계다.
Step string
// ReleaseName 은 Helm 릴리스명이다. 파드 이름 접두사이기도 하다.
ReleaseName string
// ServiceName / ServicePort 는 S3 API 가 서는 클러스터 내부 주소다.
ServiceName string
ServicePort int
// CredentialSecret 은 provisioning_secrets 가 금고에서 옮겨 오는 자격 Secret 이다.
// 차트가 existingSecret 으로 읽으므로 키 이름은 차트가 정한다.
CredentialSecret string
AccessKeyKey string
SecretKeyKey string
// VaultAccessKeyPath / VaultSecretKeyPath 는 스택 금고 접두사 뒤의 경로다.
// 자격의 원천이다 — GitLab 의 연결 Secret 도 같은 경로에서 만든다.
VaultAccessKeyPath string
VaultSecretKeyPath string
}
ObjectStorageBackend 는 스택 안에 세우는 S3 호환 오브젝트 스토리지 구현체 하나다.
func ObjectStorageBackendFor ¶ added in v0.6.0
func ObjectStorageBackendFor(sel ToolSelection) (ObjectStorageBackend, bool)
ObjectStorageBackendFor 는 storage_backend 선택에 맞는 구현체를 돌려준다.
고른 이름이 구현체를 가리키면 그것이다. 그 밖의 이름(빈 이름 포함)은 MinIO 다 — 이 슬롯은 오래 이름을 보지 않고 무엇이든 MinIO 를 세웠고, 이름 없이 저장된 스택이 재시도에서 다른 구현체를 깔면 이미 쌓인 오브젝트를 잃는다. 이름으로 고르는 것은 표에 있는 구현체로만 넓힌다.
func ObjectStorageBackendForStep ¶ added in v0.6.0
func ObjectStorageBackendForStep(step string) (ObjectStorageBackend, bool)
ObjectStorageBackendForStep 은 설치 단계로 구현체를 찾는다.
func ObjectStorageBackendNamed ¶ added in v0.6.0
func ObjectStorageBackendNamed(name string) (ObjectStorageBackend, bool)
ObjectStorageBackendNamed 는 이름이 가리키는 구현체를 찾는다. 빈 이름은 MinIO 다.
호환성 매트릭스가 이것으로 슬롯을 대조에서 뺀다 — 구현체는 S3 계약으로 갈아 끼우므로 도구 조합을 가르지 않는다. 표에 없는 이름(s3·gcs 처럼 클러스터 밖 제공자)은 찾지 못한 것으로 돌려 지금처럼 매트릭스 검사를 받게 한다.
func ObjectStorageBackends ¶ added in v0.6.0
func ObjectStorageBackends() []ObjectStorageBackend
ObjectStorageBackends 는 스택이 세울 수 있는 구현체 전부다.
func (ObjectStorageBackend) Endpoint ¶ added in v0.6.0
func (b ObjectStorageBackend) Endpoint(namespace string) string
Endpoint 는 같은 클러스터 안의 소비자가 붙을 S3 엔드포인트다.
type OrgStackImageScan ¶ added in v0.6.0
type OrgStackImageScan struct {
Stack *Stack
Report StackImageScanReport
}
OrgStackImageScan 은 조직 스택 하나와 그 설치 이미지 스캔 보고서다. 보안 대시보드(#65)가 스택 모듈의 공개 경로(usecase.ScanStackImages.ReportsForOrg)로 읽는다.
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 ¶
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 ¶
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 SecurityConfig ¶ added in v0.6.0
type SecurityConfig struct {
ImageScanner ToolSelection `json:"image_scanner,omitempty"`
// SAST 는 소스 정적 분석 서버다(SonarQube Community). 이미지 스캐너와 같은
// 선택 슬롯이다 — 고르지 않으면 설치되지 않고, 그 스택의 파이프라인은 SAST
// 단계를 켤 수 없다.
SAST ToolSelection `json:"sast,omitempty"`
// SCA 는 서드파티 의존성 취약점 스캔이다(nullus-plan#79). 선택지는 Trivy 하나고 따로 설치하는
// 것이 없다 — 파이프라인의 의존성 스캔 단계가 스택의 Trivy 서버에 붙는다. 그래서 이것만 골라도
// Trivy 서버가 선다(HasTrivyServer). 고르지 않으면 그 스택의 파이프라인에 단계가 없다.
SCA ToolSelection `json:"sca,omitempty"`
}
SecurityConfig holds tool selections for the security step.
이미지 스캐너는 선택이다 — 고르지 않으면 설치되지 않고, 그 스택의 파이프라인은 이미지 스캔 단계를 켤 수 없다. 레지스트리가 Harbor 면 Harbor 내장 스캐너로 대신할 수 있다(스캔 소스 판단은 cicd 모듈이 한다).
지원 레지스트리 5종 중 자체 스캔 기능이 있는 것은 Harbor 뿐이라, 나머지 구성에서는 이 자리를 고르지 않으면 이미지를 검사할 수단이 아예 없다.
type SharedComponent ¶ added in v0.6.0
type SharedComponent struct {
}
SharedComponent 는 스택이 쓰는 클러스터 공용 구성요소 하나다(스택 네임스페이스 밖).
func SharedComponents ¶ added in v0.6.0
func SharedComponents() []SharedComponent
SharedComponents 는 스택이 쓰는 공용 구성요소다. 설치 이미지 스캔이 스택 네임스페이스와 함께 본다 — 그 이미지의 CVE 도 스택의 위험이다. 클러스터에 이미 있던 것을 재사용했어도 스택이 쓰므로 넣는다. 네임스페이스는 설치기가 못박은 곳이다(cert-manager · metrics-server 는 chart spec, ESO 는 ESONamespace).
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"`
Security SecurityConfig `json:"security"`
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 StackImageScan ¶ added in v0.6.0
type StackImageScan struct {
StackID string
// Image 는 파드 스펙에 적힌 표기(태그)다. 사람이 읽는 이름이다.
Image string
// ImageDigest 에 결과를 붙인다 — 태그는 움직인다.
ImageDigest string
Release string
Workloads []string
// Namespace 는 이미지를 돌리는 파드의 네임스페이스다. Shared 는 그것이 스택 네임스페이스 밖의
// 클러스터 공용 구성요소(cert-manager 등)라는 뜻이다.
Namespace string
// Exposed 는 이 이미지를 쓰는 파드가 게이트웨이(HTTPRoute)로 클러스터 밖에 열려 있는지다.
// ExposedHosts 는 그 HTTPRoute 의 호스트 이름이다(호스트를 적지 않은 경로면 비어 있다).
// 같은 CVE 라도 밖에서 닿는 서비스의 것을 먼저 고친다(설치 OSS CVE 대응 정책).
Exposed bool
ExposedHosts []string
Status ImageScanStatus
Error string
// Counts 는 모든 취약점, FixableCounts 는 수정본이 있는 것만 센 값이다.
// 스캔하지 못한 이미지는 nil 이다 — 0 으로 채우면 "취약점 0건" 으로 읽힌다.
Counts *shareddomain.SeverityCounts
FixableCounts *shareddomain.SeverityCounts
ScannerVersion string
DBUpdatedAt *time.Time
ScannedAt time.Time
// Vulnerabilities 는 취약점 목록이다. VulnerabilitiesRecorded 가 거짓이면 목록을
// 모른다(스캔 실패, 목록 기능 전 스캔) — 빈 목록과 다르다.
Vulnerabilities []shareddomain.ImageVulnerability
VulnerabilitiesRecorded bool
}
StackImageScan 은 스택이 돌리는 이미지 하나의 스캔 결과다.
type StackImageScanReport ¶ added in v0.6.0
type StackImageScanReport struct {
StackID string
Status ImageScanState
Reason ImageScanSkipReason
// Airgap 은 에어갭 설치의 결과라는 뜻이다. 취약점 DB 가 번들을 반입한 날짜 기준이다.
Airgap bool
LastScannedAt *time.Time
// Summary 는 스캔에 성공한 이미지의 건수 합이다.
Summary *shareddomain.SeverityCounts
Items []StackImageScan
}
StackImageScanReport 는 스택 하나의 설치 이미지 스캔 보고서다.
func BuildImageScanReport ¶ added in v0.6.0
func BuildImageScanReport(stackID string, reason ImageScanSkipReason, scans []StackImageScan) StackImageScanReport
BuildImageScanReport 는 저장된 결과로 보고서를 만든다.
스캔하지 않는 스택은 예전 결과를 싣지 않는다 — 에어갭으로 옮긴 스택의 오래된 결과가 현재 상태처럼 읽히면 안 된다.
type StackImageVulnerabilities ¶ added in v0.6.0
type StackImageVulnerabilities struct {
// Found 는 그 이미지의 스캔 결과가 있는지다.
Found bool
// Recorded 는 목록을 저장했는지다. 거짓이면 Items 가 비어도 0건이 아니다.
Recorded bool
Items []shareddomain.ImageVulnerability
}
StackImageVulnerabilities 는 설치 이미지 하나의 저장된 취약점 목록이다.
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 ToolImageProfile ¶ added in v0.6.0
type ToolImageProfile struct {
// Tool 은 호환성 매트릭스의 도구 이름이다.
Tool string
// Step 은 이 도구를 설치하는 단계다.
Step string
// NativeArchs 는 공식 이미지가 내는 아키텍처다.
NativeArchs []string
// Sources 는 공식 이미지가 못 덮는 클러스터에 쓸 대체 출처다. 앞의 것이 먼저다.
Sources []ArchImageSource
}
ToolImageProfile 은 도구 하나가 어느 아키텍처의 노드에서 뜰 수 있는지를 말한다.
공식 이미지가 모든 아키텍처를 내는 도구는 여기에 없다. 여기 선언이 설치(이미지 선택·사전검사)와 호환성 매트릭스의 ArchSupport 가 함께 보는 단일 기준이다 — 매트릭스가 따로 적으면 설치가 실제로 내는 이미지와 어긋나도 아무것도 깨지지 않았고, 그래서 arm64 에서 뜨지 않는 Harbor 를 Pre-Deploy Gate 가 통과시켰다.
func ToolImageProfileForStep ¶ added in v0.6.0
func ToolImageProfileForStep(step string) (ToolImageProfile, bool)
ToolImageProfileForStep 은 설치 단계의 프로파일을 찾는다.
func ToolImageProfileForTool ¶ added in v0.6.0
func ToolImageProfileForTool(name string) (ToolImageProfile, bool)
ToolImageProfileForTool 은 매트릭스의 도구 이름으로 프로파일을 찾는다.
func ToolImageProfiles ¶ added in v0.6.0
func ToolImageProfiles() []ToolImageProfile
ToolImageProfiles 는 선언된 프로파일 전부의 사본을 돌려준다.
func (ToolImageProfile) Resolve ¶ added in v0.6.0
func (p ToolImageProfile) Resolve(nodeArchs []string) ImageSourceResolution
Resolve 는 클러스터의 노드 아키텍처에서 쓸 이미지 출처를 고른다.
- 노드를 모르면(빈 목록) 판단하지 않고 공식 이미지를 쓴다.
- 공식 이미지가 모든 노드를 덮으면 공식 이미지를 쓴다.
- 아니면 모든 노드를 덮는 첫 대체 출처를 쓴다.
- 그런 출처가 없으면 못 뜨는 아키텍처를 Unsupported 로 돌려준다.
func (ToolImageProfile) SupportedArchs ¶ added in v0.6.0
func (p ToolImageProfile) SupportedArchs() []string
SupportedArchs 는 공식 이미지나 대체 출처로 뜰 수 있는 아키텍처다(정렬).
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 TrivyServerSelection ¶ added in v0.6.0
func TrivyServerSelection(cfg StackConfig) ToolSelection
TrivyServerSelection 은 Trivy 서버의 버전·계획을 정하는 선택이다. 이미지 스캐너를 골랐으면 그것이 기준이고, 의존성 스캔만 골랐으면 그 선택이 서버를 대표한다. 서버가 서지 않으면 빈 선택이다.
계획(applied_resource_overrides)은 이 선택을 이미지 스캐너 슬롯(security.imageScanner)에 싣는다 — 설치 단계는 슬롯 하나로 계획을 찾으므로, 의존성 스캔만 고른 스택도 같은 자리로 서버 크기를 받는다.
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 ¶
ToolWorkload 는 스택 설정이 클러스터에 실제로 띄우는 OSS 하나를 가리킨다.
NamePrefixes 는 그 OSS 가 만드는 파드·워크로드 이름의 접두사다. 릴리스명이 곧 이름 접두사가 되므로 설치 경로가 쓰는 릴리스 상수와 같은 값을 쓴다.
func InstalledToolWorkloads ¶
func InstalledToolWorkloads(cfg StackConfig) []ToolWorkload
InstalledToolWorkloads 는 스택 설정에서 "이 스택이 클러스터에 설치하는 OSS" 목록을 뽑는다. 모니터링이 무엇을 보여줄지 정하는 단일 기준점이다 — 스택 상세 화면과 플랫폼 대시보드가 같은 답을 보게 하려면 양쪽 다 이 함수를 거쳐야 한다.
여기에 없는 OSS 는 파드가 멀쩡히 떠 있어도 어느 화면에도 나오지 않는다.
type UpgradeBundle ¶ added in v0.6.0
type UpgradeBundle struct {
ID string `json:"id"`
Tool string `json:"tool"`
ReleaseName string `json:"release_name"`
ChartName string `json:"chart_name"`
RepoURL string `json:"repo_url"`
SourceChartVersion string `json:"source_chart_version"`
SourceAppVersion string `json:"source_app_version"`
TargetChartVersion string `json:"target_chart_version"`
TargetAppVersion string `json:"target_app_version"`
RiskLevel string `json:"risk_level"`
ExpectedDisruption string `json:"expected_disruption"`
ReleaseNotes string `json:"release_notes,omitempty"`
RequiresBackup bool `json:"requires_backup"`
SupportedArchitectures []string `json:"supported_architectures,omitempty"`
Status string `json:"status"`
// FixesCVEs 는 이 업그레이드가 고치는 CVE 다. 번들을 리허설할 때 함께 등록한다 — 설치 OSS CVE
// 대응(nullus-plan#78)이 "어느 검증된 업그레이드가 이 CVE 를 고치는가" 를 여기서 읽는다.
FixesCVEs []string `json:"fixes_cves,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
func NewUpgradeBundle ¶ added in v0.6.0
func NewUpgradeBundle(in NewUpgradeBundleInput) (*UpgradeBundle, error)
NewUpgradeBundle 은 등록 입력을 검사해 번들을 만든다. 버전은 읽을 수 있어야 하고 대상이 출발보다 높아야 한다 — 내려가는 경로나 같은 버전은 업그레이드가 아니다.
func SelectUpgradeBundle ¶ added in v0.6.0
func SelectUpgradeBundle(bundles []UpgradeBundle) *UpgradeBundle
SelectUpgradeBundle 은 같은 출발점의 번들 중 가장 높은 대상 버전을 고른다. 읽을 수 없는 버전은 읽을 수 있는 버전보다 뒤로 민다.
func (*UpgradeBundle) ChangeStatus ¶ added in v0.6.0
func (b *UpgradeBundle) ChangeStatus(to string, rehearsalConfirmed bool) error
ChangeStatus 는 번들의 상태를 바꾼다. verified 로 올리는 데는 리허설 확인이 필요하고, revoked 는 끝이다 — 거둔 경로를 되살리려면 다시 리허설해 새로 등록한다.
type UpgradeCandidate ¶ added in v0.6.0
type UpgradeCandidate struct {
Tool string `json:"tool"`
ReleaseName string `json:"release_name"`
CurrentChartVersion string `json:"current_chart_version"`
CurrentAppVersion string `json:"current_app_version"`
CurrentRevision int `json:"current_revision"`
ReleaseStatus string `json:"release_status"`
Bundle *UpgradeBundle `json:"bundle,omitempty"`
BlockedReason string `json:"blocked_reason,omitempty"`
// FixesFound 는 번들이 고치는 CVE 중 이 스택의 그 릴리스 이미지에서 지금 발견된 것이다.
FixesFound []string `json:"fixes_found,omitempty"`
// FixesChecked 는 그 릴리스의 스캔 결과로 확인했는지다. 거짓이면 FixesFound 가 비어도 "이 스택엔
// 없다" 가 아니다(스캐너가 없거나 아직 스캔하지 않았거나 읽지 못했다).
FixesChecked bool `json:"fixes_checked,omitempty"`
LastRun *UpgradeRun `json:"last_run,omitempty"`
CheckedAt time.Time `json:"checked_at"`
}
UpgradeCandidate 는 스택에 실제로 설치된 릴리스와 거기서 갈 수 있는 검증 경로다. Bundle 이 없다는 것은 "검증된 업그레이드 경로가 없다" 는 뜻이지 최신이라는 뜻이 아니다.
func NewUpgradeCandidate ¶ added in v0.6.0
func NewUpgradeCandidate(tool, releaseName, chartVersion, appVersion string, revision int, releaseStatus string, bundle *UpgradeBundle, now time.Time) UpgradeCandidate
type UpgradeCheck ¶ added in v0.6.0
type UpgradeCheck struct {
Name string `json:"name"`
Status string `json:"status"` // pass | warning | blocked
Message string `json:"message"`
Remediation string `json:"remediation,omitempty"`
}
func BlockedCheck ¶ added in v0.6.0
func BlockedCheck(name, message, remediation string) UpgradeCheck
func EvaluateUpgradeBackup ¶ added in v0.6.0
func EvaluateUpgradeBackup(finishedAt time.Time, found bool, now time.Time, maxAge time.Duration) UpgradeCheck
EvaluateUpgradeBackup 은 마지막 복구 가능 백업으로 백업 점검을 만든다. 오래된 백업은 없는 것과 같다 — 그 사이의 변경은 되돌릴 수 없다.
func PassedCheck ¶ added in v0.6.0
func PassedCheck(name, message string) UpgradeCheck
type UpgradeRun ¶ added in v0.6.0
type UpgradeRun struct {
ID string `json:"id"`
StackID string `json:"stack_id"`
BundleID string `json:"bundle_id"`
Tool string `json:"tool"`
Status string `json:"status"`
CurrentStep string `json:"current_step"`
RequestedBy string `json:"requested_by"`
Reason string `json:"reason"`
IdempotencyKey string `json:"-"`
SourceChartVersion string `json:"source_chart_version"`
TargetChartVersion string `json:"target_chart_version"`
PreviousRevision int `json:"previous_revision"`
ResultRevision int `json:"result_revision,omitempty"`
Checks []UpgradeCheck `json:"checks"`
Error string `json:"error,omitempty"`
StartedAt time.Time `json:"started_at"`
UpdatedAt time.Time `json:"updated_at"`
FinishedAt *time.Time `json:"finished_at,omitempty"`
}
func NewUpgradeRun ¶ added in v0.6.0
func NewUpgradeRun(in NewUpgradeRunInput) (*UpgradeRun, error)
NewUpgradeRun 은 사전 점검이 끝난 요청으로 실행을 만든다. 점검이 막혔으면 곧바로 끝난 실행(blocked)이 된다 — 시도와 막힌 이유도 감사 기록이다.
func (*UpgradeRun) Active ¶ added in v0.6.0
func (r *UpgradeRun) Active() bool
func (*UpgradeRun) BeginRollback ¶ added in v0.6.0
func (r *UpgradeRun) BeginRollback(cause error, now time.Time)
func (*UpgradeRun) EnterHealthCheck ¶ added in v0.6.0
func (r *UpgradeRun) EnterHealthCheck(revision int, now time.Time)
func (*UpgradeRun) Fail ¶ added in v0.6.0
func (r *UpgradeRun) Fail(cause error, now time.Time)
Fail 은 Helm 이 릴리스를 바꾸기 전에 실패한 실행을 닫는다 — 되돌릴 것이 없다.
func (*UpgradeRun) Interrupt ¶ added in v0.6.0
func (r *UpgradeRun) Interrupt(now time.Time)
Interrupt 는 작업 중에 API 가 사라진 실행을 닫는다. Helm 릴리스가 어디까지 갔는지 모르므로 자동으로 되돌리지 않고 사람에게 넘긴다.
func (*UpgradeRun) RequireManualIntervention ¶ added in v0.6.0
func (r *UpgradeRun) RequireManualIntervention(cause error, now time.Time)
func (*UpgradeRun) RolledBack ¶ added in v0.6.0
func (r *UpgradeRun) RolledBack(now time.Time)
func (*UpgradeRun) Stale ¶ added in v0.6.0
func (r *UpgradeRun) Stale(now time.Time) bool
Stale 은 진행 중인데 심장 박동이 끊긴 실행이다.
func (*UpgradeRun) Succeed ¶ added in v0.6.0
func (r *UpgradeRun) Succeed(now time.Time)
func (*UpgradeRun) Terminal ¶ added in v0.6.0
func (r *UpgradeRun) Terminal() bool
Source Files
¶
- access_domain.go
- arch_image_source.go
- compatibility.go
- config.go
- connection.go
- cve_findings.go
- deploy_steps.go
- gateway_backends.go
- gateway_host_aliases.go
- helm_releases.go
- helm_step_metadata.go
- history.go
- image_scan.go
- object_storage.go
- planning.go
- planning_plan.go
- release_values.go
- resource_default.go
- sast.go
- sca.go
- shared_cluster_resources.go
- stack.go
- stack_namespace.go
- template.go
- tool_access_url.go
- tool_workload.go
- upgrade.go
- upgrade_bundle.go