Documentation
¶
Index ¶
- Variables
- type AccessTokenSpec
- type BuildDelegate
- type CDApplicationDeleter
- type CIBuild
- type CIBuildReader
- type CIBuildTrigger
- type CICDGoldenPathRepository
- type CICredentialResolver
- type CIJob
- type CIJobProvisioner
- type CIJobSpec
- type CIPlatform
- type CIStage
- type CIStageStatus
- type ClusterTarget
- type ClusterTargetProvider
- type CommitFile
- type CommitSpec
- type DelegateBuildOpts
- type DeploymentRepository
- type GroupSpec
- type ImagePreparer
- type ImageRegistryResolver
- type ImageRepositoryDeleter
- type ImageTarget
- type ImageTargetSpec
- type KubeconfigProvider
- type ManifestApplier
- type OrgMemberProvisioner
- type PipelineConfigurator
- type PipelineCredentialPlane
- type PipelineRepository
- type PipelineTemplateRepository
- type PipelineVariable
- type PrepareImageOpts
- type ProjectSpec
- type ProjectVariable
- type RegistryCredentialResolver
- type RegistryKind
- type SCMBundle
- type SCMBundleFactory
- type SCMConnection
- type SCMConnectionReader
- type SCMGroup
- type SCMPlatform
- type SCMProject
- type SCMProvisioner
- type SCMTokenIssuer
- type SCMTokenSpec
- type SCMWebhookProvisioner
- type StackReader
- type StackSummary
- type WorkloadDeleter
Constants ¶
This section is empty.
Variables ¶
var ErrImageDeletionUnsupported = errors.New("이 레지스트리는 이미지 저장소 삭제를 지원하지 않습니다")
ErrImageDeletionUnsupported 는 이 레지스트리에서 이미지 저장소를 지울 수단이 없음을 알린다.
조용히 건너뛰지 않는 이유는, 사용자가 "이미지도 삭제" 를 골랐는데 아무 일도 일어나지 않으면 지워진 줄 알고 넘어가기 때문이다. Harbor·Nexus 는 삭제에 관리자 자격증명이 따로 필요해 파이프라인 삭제 경로에서는 아직 다루지 않는다.
var ErrSCMUserNotFound = errors.New("SCM 사용자 계정을 찾지 못했습니다")
ErrSCMUserNotFound 는 그 이메일의 SCM 계정이 아직 없다는 뜻이다.
실패가 아니라 "아직" 이다 — OIDC 첫 로그인 전에는 계정이 존재하지 않는다. 호출부는 이것을 경고로 옮겨 담아야 한다.
ErrStackToolsUnavailable 은 이 스택의 도구에 닿을 수 없다는 뜻이다.
스택이 지워졌거나 아직 설치 중일 때다. 둘 다 "지금은 그 도구들에 아무것도 할 수 없다" 는 같은 상황이고, 호출부는 그것을 실패가 아니라 **할 수 없는 일**로 다뤄야 한다 — 스택이 사라진 파이프라인을 영영 못 지우게 되면 좀비가 남는다.
Functions ¶
This section is empty.
Types ¶
type AccessTokenSpec ¶
type AccessTokenSpec struct {
Name string
Scopes []string
// ExpiresInDays 가 0 이면 구현체 기본값을 쓴다.
ExpiresInDays int
}
AccessTokenSpec 은 프로젝트 범위 토큰 발급 요청이다.
type BuildDelegate ¶
type BuildDelegate interface {
// DelegateBuild 는 러너의 실행을 시작시키고 그 실행의 주소를 돌려준다.
DelegateBuild(ctx context.Context, opts DelegateBuildOpts) (runURL string, err error)
}
BuildDelegate 는 이미지 빌드를 스택의 CI 러너에 넘긴다.
ImagePreparer 와 짝을 이루는 반대편이다. ImagePreparer 는 플랫폼이 직접 빌드하는 장애 대응 경로(emergency_direct)이고, 이쪽은 스택 컴포넌트가 실행하는 일반 경로(stack_integrated)다 — CI 가 빌드해 레지스트리에 올리고 CD 도구가 클러스터에 반영한다. 플랫폼은 실행을 시작시키고 결과를 들여올 뿐 git clone·docker build·kubectl apply 를 하지 않는다.
type CDApplicationDeleter ¶
type CDApplicationDeleter interface {
// DeleteApplication 은 애플리케이션이 이미 없으면 성공으로 본다 —
// 삭제의 목표는 "없는 상태" 이고, 없음을 오류로 올리면 재시도가 끝나지 않는다.
DeleteApplication(ctx context.Context, kubeconfig []byte, namespace, name string) error
}
CDApplicationDeleter 는 CD 도구가 배포한 애플리케이션을 지운다.
도구 이름을 계약에 넣지 않는다. Argo CD 든 다른 것이든 "배포된 애플리케이션을 지운다" 는 같은 일이고, 도구가 바뀌면 구현체만 갈아 끼우면 된다.
애플리케이션만 지우면 Deployment·Service·HTTPRoute 가 클러스터에 남아 앱이 계속 돈다. 구현체는 그 도구의 방식대로 배포된 리소스까지 함께 걷어내야 한다 (Argo CD 는 정리 finalizer 를 붙인다).
type CIBuild ¶
type CIBuild struct {
Number int
// Result 는 CI 가 보고한 결과다(SUCCESS/FAILURE/ABORTED). 실행 중이면 빈 값이다.
Result string
Building bool
// StartedAt 은 빌드 시작 시각, Duration 은 실행 시간이다.
// 실행 중인 빌드의 Duration 은 0 이다.
StartedAt time.Time
Duration time.Duration
// Stages 는 실행 안의 단계다. CI 가 단계 정보를 주지 않으면 비어 있다 —
// 비어 있는 것과 "모두 성공" 은 다르다.
Stages []CIStage
}
CIBuild 는 CI 서버가 실행한 빌드 하나다.
type CIBuildReader ¶
type CIBuildReader interface {
ListBuilds(ctx context.Context, jobName, branch string, limit int) ([]CIBuild, error)
}
CIBuildReader 는 CI 서버에서 빌드 이력을 읽는다.
플랫폼이 직접 배포하는 경로와 달리, GitOps 경로의 실행 기록은 CI 서버가 갖고 있다. 이것을 들이지 않으면 빌드가 성공해도 화면의 실행 통계가 영원히 0 으로 남는다.
type CIBuildTrigger ¶
CIBuildTrigger 는 CI 서버의 job 을 지금 실행시킨다.
webhook 은 커밋이 있을 때만 돈다. 사용자가 화면에서 "배포 실행" 을 누르는 것은 커밋 없이 지금 실행하겠다는 뜻이라, 트리거가 따로 필요하다.
type CICDGoldenPathRepository ¶
type CICDGoldenPathRepository interface {
GetByID(ctx context.Context, id string) (*domain.CICDGoldenPath, error)
List(ctx context.Context) ([]*domain.CICDGoldenPath, error)
Create(ctx context.Context, goldenPath *domain.CICDGoldenPath) error
Update(ctx context.Context, goldenPath *domain.CICDGoldenPath) error
Delete(ctx context.Context, id string) error
}
CICDGoldenPathRepository defines the interface for CI/CD Golden Path persistence.
type CICredentialResolver ¶
type CICredentialResolver interface {
ResolveCICredential(ctx context.Context, spec SCMTokenSpec) (user, secret string, err error)
}
CICredentialResolver 는 스택별 CI 서버 접속 자격증명을 돌려준다.
기동 시점에 고정할 수 없다 — CI 서버는 스택마다 따로 서고 관리자 비밀번호도 스택마다 다르게 생성된다(provisioning_secrets 가 OpenBao 에 넣는다). 고정 문자열을 쓰면 비어 있거나 다른 스택의 자격증명으로 붙게 된다.
SCMTokenSpec 을 재사용한다 — 스택·클러스터·조직·환경이라는 조회 축이 SCM 토큰과 완전히 같기 때문이다.
type CIJobProvisioner ¶
type CIJobProvisioner interface {
// EnsureJob 은 job 을 만들거나 이미 있으면 그대로 둔다(멱등).
EnsureJob(ctx context.Context, spec CIJobSpec) (*CIJob, error)
// DeleteJob 은 job 을 지운다. 이미 없으면 성공으로 본다.
DeleteJob(ctx context.Context, name string) error
}
CIJobProvisioner 는 CI 서버에 job 을 만든다.
SCMProvisioner 와 분리한다. GitLab CI·GitHub Actions 는 파이프라인 정의를 푸시하면 자동으로 감지하지만, Jenkins 는 job 이 먼저 존재해야 한다 — Jenkinsfile 만 커밋해서는 아무 일도 일어나지 않는다. 그 차이를 흡수하는 자리이므로 이 포트를 지원하지 않는 플랫폼에서는 nil 이고, 호출부는 nil 이면 건너뛴다(기존 GitLab/GitHub 경로 무영향).
type CIJobSpec ¶
type CIJobSpec struct {
// Name 은 job 이름이다. 앱 이름과 같게 두어 화면에서 짝을 찾기 쉽게 한다.
Name string
// RepoCloneURL 은 CI 가 스캔할 저장소 주소다.
RepoCloneURL string
// RepoOwner / RepoName 은 organization 소스가 요구하는 분해된 형태다.
RepoOwner string
RepoName string
// ServerURL 은 SCM 서버의 루트 주소다. Gitea 소스는 리포 주소가 아니라
// 서버 주소를 받아 API 로 브랜치를 훑는다.
ServerURL string
// CredentialID 는 CI 서버에 등록된 SCM 자격증명 식별자다.
// 비어 있으면 익명으로 스캔한다 — private 리포에서는 실패한다.
CredentialID string
// PipelinePath 는 파이프라인 정의 파일의 리포 내 경로다.
PipelinePath string
}
CIJobSpec 은 CI 서버에 만들 job 하나의 요청이다.
type CIPlatform ¶
type CIPlatform string
CIPlatform 은 파이프라인을 실행하는 CI 플랫폼이다.
SCM 과 별개의 축이다. GitLab·GitHub 은 SCM 이 CI 를 겸하지만 Gitea 는 그렇지 않다 — 소스는 Gitea, 빌드는 Jenkins 처럼 갈린다. 하나로 묶어 두면 Gitea 스택에 .gitlab-ci.yml 이 깔리고 Jenkins 는 읽을 파일이 없어 영영 돌지 않는다.
const ( // CIPlatformGitLabCI / CIPlatformGitHubActions 는 SCM 이 겸하는 CI 다. CIPlatformGitLabCI CIPlatform = "gitlab-ci" CIPlatformGitHubActions CIPlatform = "github-actions" // CIPlatformJenkins 는 SCM 과 독립적으로 도는 CI 다. CIPlatformJenkins CIPlatform = "jenkins" )
func DefaultCIPlatformFor ¶
func DefaultCIPlatformFor(platform SCMPlatform) CIPlatform
DefaultCIPlatformFor 는 CI 를 명시하지 않았을 때 SCM 이 함의하는 CI 다.
Gitea 는 자체 CI 를 쓰지 않으므로 Jenkins 로 본다 — Gitea 스택에 .gitlab-ci.yml 을 깔면 아무것도 그것을 읽지 않는다.
type CIStageStatus ¶
type CIStageStatus string
CIStageStatus 는 단계 상태의 정규화된 어휘다.
CI 마다 어휘가 다르다 — Jenkins 는 SUCCESS/FAILED/IN_PROGRESS/NOT_EXECUTED, GitLab 은 success/failed/running/pending/skipped, GitHub Actions 는 status 와 conclusion 두 필드로 나눠 표현한다.
이 변환을 어댑터 경계에서 끝낸다. 도메인과 화면이 CI 별 어휘를 알게 되면 OSS 를 하나 늘릴 때마다 위쪽 계층이 모두 바뀐다.
const ( CIStageSuccess CIStageStatus = "success" CIStageFailed CIStageStatus = "failed" CIStageRunning CIStageStatus = "running" CIStageQueued CIStageStatus = "queued" // CIStageSkipped 는 조건 때문에 실행되지 않은 단계다. // 실패와 구분해야 한다 — 건너뛴 것은 잘못된 것이 아니다. CIStageSkipped CIStageStatus = "skipped" // CIStageUnknown 은 CI 가 상태를 알려주지 않은 경우다. // 성공으로 넘겨짚지 않는다 — 실행되지 않은 일을 성공이라 말하면 안 된다. CIStageUnknown CIStageStatus = "unknown" )
func NormalizeStageStatus ¶
func NormalizeStageStatus(raw string) CIStageStatus
NormalizeStageStatus 는 CI 가 쓰는 표현을 정규화된 어휘로 옮긴다.
어댑터가 자기 CI 의 표현을 여기 넘긴다. 모르는 값은 unknown 이다 — 넘겨짚으면 돌지 않은 단계가 성공으로 보인다.
type ClusterTarget ¶
type ClusterTargetProvider ¶
type ClusterTargetProvider interface {
GetTarget(ctx context.Context, clusterID string) (*ClusterTarget, error)
}
type CommitFile ¶
CommitFile 은 커밋에 포함할 파일 하나다.
type CommitSpec ¶
type CommitSpec struct {
Branch string
Message string
Files []CommitFile
}
CommitSpec 은 여러 파일을 한 커밋으로 올리는 요청이다.
type DelegateBuildOpts ¶
type DelegateBuildOpts struct {
StackID string
// JobName 은 CI 서버의 job 이름이다. 프로비저닝이 앱 이름으로 만든다.
JobName string
// Branch 는 실행할 브랜치다. multibranch job 은 브랜치가 하위 job 이라
// 이것이 없으면 무엇을 실행할지 정해지지 않는다.
Branch string
// DeploymentID 는 진행 상황을 기록할 배포 기록이다.
DeploymentID string
// StepIndex 는 이 작업이 기록될 단계 번호다.
StepIndex int
}
DelegateBuildOpts 는 어느 스택의 어느 job 을 실행할지다.
type DeploymentRepository ¶
type DeploymentRepository interface {
Create(ctx context.Context, deployment *domain.Deployment) error
GetByID(ctx context.Context, id string) (*domain.Deployment, error)
ListByPipelineID(ctx context.Context, pipelineID string) ([]*domain.Deployment, error)
Update(ctx context.Context, deployment *domain.Deployment) error
}
DeploymentRepository defines the interface for deployment persistence.
type ImagePreparer ¶
type ImagePreparer interface {
PrepareImage(ctx context.Context, opts PrepareImageOpts) (imageRef string, err error)
}
type ImageRegistryResolver ¶
type ImageRegistryResolver interface {
Resolve(ctx context.Context, spec ImageTargetSpec) (*ImageTarget, error)
}
ImageRegistryResolver 는 스택 구성에 맞는 이미지 저장 위치를 결정한다.
type ImageRepositoryDeleter ¶
type ImageRepositoryDeleter interface {
DeleteImageRepository(ctx context.Context, target *ImageTarget) error
}
ImageRepositoryDeleter 는 레지스트리에서 이미지 저장소를 통째로 지운다.
태그 하나가 아니라 저장소 전체가 대상이다. 파이프라인을 지우는 맥락에서는 그 앱의 이미지가 전부 필요 없어지기 때문이다.
type ImageTarget ¶
type ImageTarget struct {
Kind RegistryKind
// Host 는 레지스트리 호스트다 (예: "registry.nullus.local").
Host string
// Repository 는 태그를 뺀 완전한 이미지 경로다
// (예: "registry.nullus.local/acme/myapp").
Repository string
// UsernameVar / PasswordVar 는 CI 가 로그인에 쓸 변수 이름이다.
// GitLab 프로젝트 레지스트리는 내장 변수를, 외부 레지스트리는
// 파이프라인에 등록된 변수를 가리킨다.
UsernameVar string
PasswordVar string
// RequiredVariables 는 파이프라인에 미리 등록돼야 하는 변수들이다.
// 내장 변수만 쓰는 구성에서는 비어 있다.
RequiredVariables []string
}
ImageTarget 은 CI 가 이미지를 올릴 위치와 인증 방법이다.
로그인 명령을 문자열로 담지 않는다 — 셸 조각이 포트에 새면 CI 플랫폼을 바꿀 때 포트까지 흔들린다. 렌더러가 이 구조를 보고 스크립트를 만든다.
type ImageTargetSpec ¶
type ImageTargetSpec struct {
// AppName 은 애플리케이션 이름이다.
AppName string
// SCMProjectPath 는 앱의 SCM 프로젝트 전체 경로다 (예: "acme/myapp").
// SCM 프로젝트 레지스트리를 쓰는 구성에서만 의미가 있다.
SCMProjectPath string
// SCMRegistryURL 은 SCM 이 알려준 프로젝트 레지스트리 경로다.
SCMRegistryURL string
// OrgPath 는 조직 그룹 경로다. Harbor 프로젝트 이름 등에 쓴다.
OrgPath string
}
ImageTargetSpec 은 이미지 저장 위치를 묻는 요청이다.
type KubeconfigProvider ¶
type ManifestApplier ¶
type OrgMemberProvisioner ¶
type OrgMemberProvisioner interface {
// EnsureOrgMember 는 이메일로 찾은 사용자를 조직에 넣는다(멱등).
EnsureOrgMember(ctx context.Context, org, email string) error
}
OrgMemberProvisioner 는 사람을 조직에 넣는다.
플랫폼이 만든 저장소는 자동화 계정 소유의 private 조직 안에 있어서, 그대로 두면 정작 그 저장소에 소스를 밀어야 할 사람이 보지도 못한다. 지원하지 않는 플랫폼에서는 nil 이며, 호출부는 nil 이면 건너뛴다.
type PipelineConfigurator ¶
type PipelineConfigurator interface {
// SetProjectVariable 은 변수를 등록하거나 이미 있으면 갱신한다.
SetProjectVariable(ctx context.Context, projectID string, v ProjectVariable) error
// CreateProjectAccessToken 은 프로젝트 범위 토큰을 발급한다.
// 값은 발급 시점에만 읽을 수 있다.
CreateProjectAccessToken(ctx context.Context, projectID string, spec AccessTokenSpec) (string, error)
}
PipelineConfigurator 는 파이프라인 실행에 필요한 설정을 프로젝트에 건다.
SCMProvisioner 와 분리한다 — 저장소 프로비저닝과 CI 설정은 플랫폼에 따라 제공 주체가 다를 수 있다(예: GitHub + 외부 CI).
type PipelineCredentialPlane ¶
type PipelineCredentialPlane interface {
Provision(ctx context.Context, app string, vars []PipelineVariable) (manifest string, err error)
}
PipelineCredentialPlane 은 파이프라인 자격증명을 준비하고 그것을 클러스터에 반영할 매니페스트를 돌려준다.
적용은 하지 않는다 — 클러스터 접근은 유스케이스가 한곳에서 맡는다.
type PipelineRepository ¶
type PipelineRepository interface {
Create(ctx context.Context, pipeline *domain.Pipeline) error
GetByID(ctx context.Context, id string) (*domain.Pipeline, error)
List(ctx context.Context, orgID string) ([]*domain.Pipeline, error)
ListByStackID(ctx context.Context, stackID string) ([]*domain.Pipeline, error)
Update(ctx context.Context, pipeline *domain.Pipeline) error
Delete(ctx context.Context, id string) error
}
PipelineRepository defines the interface for pipeline persistence.
type PipelineTemplateRepository ¶
type PipelineTemplateRepository interface {
GetByID(ctx context.Context, id string) (*domain.PipelineTemplate, error)
List(ctx context.Context) ([]*domain.PipelineTemplate, error)
Create(ctx context.Context, tmpl *domain.PipelineTemplate) error
Update(ctx context.Context, tmpl *domain.PipelineTemplate) error
Delete(ctx context.Context, id string) error
}
PipelineTemplateRepository defines the interface for pipeline template persistence.
type PipelineVariable ¶
PipelineVariable 은 파이프라인이 환경변수로 읽을 값 하나다.
type PrepareImageOpts ¶
type ProjectSpec ¶
type ProjectSpec struct {
Name string
Path string
// GroupID 는 생성 시 네임스페이스 지정에 쓴다(숫자 ID).
GroupID string
// GroupPath 는 조회 시 경로 조합에 쓴다("{GroupPath}/{Path}").
// 비면 개인 네임스페이스로 간주해 Path 만으로 조회한다.
GroupPath string
Description string
// Visibility 는 private | internal | public. 비면 private.
Visibility string
// InitReadme 가 true 면 기본 브랜치가 즉시 생성된다.
// 브랜치가 없으면 파일 커밋이 실패하므로 첫 커밋 전에는 켜야 한다.
InitReadme bool
}
ProjectSpec 은 프로젝트 생성 요청이다.
GroupID 가 비면 인증 사용자의 개인 네임스페이스에 만들어진다.
type ProjectVariable ¶
type ProjectVariable struct {
Key string
Value string
// Masked 는 job 로그에서 값을 가린다. 자격증명에는 반드시 켠다.
Masked bool
// Protected 를 켜면 보호 브랜치에서만 노출된다.
Protected bool
}
ProjectVariable 은 파이프라인에 등록할 CI/CD 변수다.
type RegistryCredentialResolver ¶
type RegistryCredentialResolver interface {
Resolve(ctx context.Context, variables []string) (map[string]string, error)
}
RegistryCredentialResolver 는 CI 가 레지스트리 로그인에 쓸 변수 값을 푼다.
요청한 변수 중 아는 것만 채워 돌려준다. 모르는 것은 손대지 않는다 — 조용히 빈 값을 채우면 CI 가 엉뚱한 자격증명으로 로그인을 시도한다.
type RegistryKind ¶
type RegistryKind string
RegistryKind 는 이미지 레지스트리 백엔드의 종류다.
스택 구성에 따라 이미지가 저장될 곳이 달라진다. GitLab 스택이면 SCM 프로젝트에 딸린 레지스트리를, Harbor 를 고른 스택이면 Harbor 프로젝트를 쓴다. CI 스크립트를 특정 레지스트리에 맞춰 쓰지 않기 위해 이 구분을 포트로 올린다.
const ( // RegistryKindSCMProject 는 소스 저장소 플랫폼이 프로젝트마다 제공하는 // 레지스트리다 (GitLab Container Registry). 저장소와 수명이 같다. RegistryKindSCMProject RegistryKind = "scm_project" // RegistryKindHarbor 는 독립 설치된 Harbor 다. RegistryKindHarbor RegistryKind = "harbor" // RegistryKindNexus 는 독립 설치된 Nexus 의 Docker 커넥터다. RegistryKindNexus RegistryKind = "nexus" // RegistryKindGHCR 은 GitHub Container Registry 다. // // 다른 종류와 달리 push 자격증명을 등록할 필요가 없다 — GitHub Actions 의 // 내장 GITHUB_TOKEN 이 packages:write 권한을 가질 수 있다. RegistryKindGHCR RegistryKind = "ghcr" // RegistryKindExternal 은 그 밖의 클러스터 외부 레지스트리다 (ECR 등). RegistryKindExternal RegistryKind = "external" )
type SCMBundle ¶
type SCMBundle struct {
Provisioner SCMProvisioner
Pipeline PipelineConfigurator
Registry ImageRegistryResolver
// Images 는 이미지 저장소를 지울 수단이다. 지원하지 않는 레지스트리에서는
// nil 이며, 호출부는 이를 ErrImageDeletionUnsupported 와 같게 다뤄야 한다
// — 조용히 건너뛰면 사용자는 이미지가 지워진 줄 안다.
Images ImageRepositoryDeleter
// CIJobs 는 CI 서버에 job 을 만드는 수단이다.
//
// GitLab CI·GitHub Actions 는 파이프라인 정의를 푸시하면 자동 감지하므로
// nil 이다. Jenkins 는 job 이 먼저 존재해야 하므로 이 자리가 채워진다.
// 호출부는 nil 이면 건너뛴다 — 기존 경로 무영향.
CIJobs CIJobProvisioner
// Webhooks 는 저장소에 push webhook 을 거는 수단이다.
// Jenkins multibranch 가 새 커밋을 알려면 필요하다. 지원하지 않으면 nil.
Webhooks SCMWebhookProvisioner
// CITrigger 는 CI 서버의 job 을 지금 실행시킨다. 지원하지 않으면 nil.
//
// 스택에 묶인 파이프라인의 "배포 실행" 이 이 자리로 온다 — 플랫폼이
// 빌드하지 않고 러너에게 넘긴다.
CITrigger CIBuildTrigger
// CIBuilds 는 CI 서버의 빌드 이력을 읽는다. 지원하지 않으면 nil.
CIBuilds CIBuildReader
// CIBaseURL 은 CI 서버의 주소다. webhook 대상 주소를 만드는 데 쓴다.
CIBaseURL string
// SCMInClusterURL 은 클러스터 안에서 SCM 에 닿는 주소다.
//
// Provisioner 의 base URL 과 구분한다 — 그쪽은 API 서버가 쓰는 주소라
// 로컬 실행에서 우회 주소(localhost 포트포워드 등)일 수 있다. 반면 이 값은
// Jenkins·Argo CD 처럼 클러스터 안에서 도는 소비자가 쓰므로 항상 서비스
// DNS 여야 한다. 둘을 같은 값으로 두면 job 이
// "Unknown server: http://localhost:3000" 으로 죽는다.
SCMInClusterURL string
// Credentials 는 CI 변수 저장소가 없는 SCM(Gitea)에서 파이프라인 자격증명을
// OpenBao → ESO → K8s Secret 평면으로 나른다. 지원하지 않으면 nil.
Credentials PipelineCredentialPlane
// CDApplications 는 CD 도구가 배포한 애플리케이션을 지우는 수단이다.
// 지원하지 않는 도구에서는 nil 이며, 호출부는 그것을 밝히고 넘어간다.
CDApplications CDApplicationDeleter
// OrgMembers 는 사람을 조직에 넣는 수단이다. 지원하지 않으면 nil.
//
// 플랫폼이 만든 저장소는 자동화 계정 소유의 private 조직 안에 있어서,
// 그대로 두면 정작 소스를 밀어야 할 사람이 보지도 못한다.
OrgMembers OrgMemberProvisioner
// RegistryCredentials 는 스택이 설치한 레지스트리(Harbor·Nexus)의 자격증명을
// 푼다. 그 값은 스택 설치가 OpenBao 에 만들어 두므로 사용자에게 다시 받을
// 이유가 없다. 플랫폼이 소유하지 않는 레지스트리에서는 아무것도 돌려주지 않는다.
RegistryCredentials RegistryCredentialResolver
// Platform 은 이 묶음이 향하는 SCM 플랫폼이다.
// 파이프라인 파일 형식이 여기서 갈리므로 렌더러까지 전달돼야 한다.
Platform SCMPlatform
// RepoAccessToken 은 플랫폼이 리포 범위 토큰 발급을 지원하지 않을 때
// Argo CD·이미지 pull 인증에 재사용할 토큰이다.
//
// GitLab 에서는 비어 있다 — 프로젝트마다 최소 권한 토큰을 따로 발급한다.
// GitHub 에는 리포 단위 토큰 API 가 없어 조직 PAT 를 그대로 쓴다.
RepoAccessToken string
// GroupPath 는 프로젝트가 만들어질 네임스페이스다.
// GitLab 은 그룹 경로, GitHub 은 organization/사용자 이름이다.
GroupPath string
// CDNamespace 는 CD 도구가 설치된 네임스페이스다.
//
// 애플리케이션 리소스는 **여기**에 산다. 배포 대상 네임스페이스(앱이 서는
// 곳)와 다르다 — 둘을 혼동하면 삭제가 없는 곳을 뒤지고 성공으로 끝난다.
CDNamespace string
// ClusterID 는 Application 을 적용할 클러스터다.
ClusterID string
// AccessDomain / GatewayName 은 배포된 앱을 외부에 노출할 때 쓴다.
// 비어 있으면 앱은 클러스터 내부에서만 접근 가능하다.
AccessDomain string
GatewayName string
}
SCMBundle 은 특정 스택에 묶인 프로비저닝 도구 묶음이다.
GitLab 주소·토큰·레지스트리 종류가 모두 스택마다 다르므로 기동 시점에 하나로 만들 수 없다. 요청 시점에 스택을 보고 조립한다.
type SCMBundleFactory ¶
SCMBundleFactory 는 스택에 맞는 도구 묶음을 조립한다.
type SCMConnection ¶
type SCMConnection struct {
Platform SCMPlatform
// Owner 는 리포지토리가 만들어질 GitHub Organization 또는 사용자 계정이다.
Owner string
// APIBaseURL 은 GitHub Enterprise Server 의 API 주소다.
// 비면 어댑터가 github.com 을 쓴다.
APIBaseURL string
}
SCMConnection 은 외부 SCM 에 붙기 위한 조직 단위 설정이다.
스택 안에 설치되는 GitLab 과 달리 GitHub 은 주소도 소유자도 우리가 정할 수 없다. 사용자가 등록한 값을 읽어야만 어느 org 에 리포를 만들지 알 수 있다.
type SCMConnectionReader ¶
type SCMConnectionReader interface {
// GetConnection 은 설정을 읽는다. 등록된 것이 없으면 nil, nil 을 돌려준다.
GetConnection(ctx context.Context, orgID string, platform SCMPlatform) (*SCMConnection, error)
}
SCMConnectionReader 는 조직에 등록된 SCM 연동 설정을 읽는다.
type SCMGroup ¶
type SCMGroup struct {
ID string `json:"id"`
Name string `json:"name"`
FullPath string `json:"full_path"`
WebURL string `json:"web_url"`
}
SCMGroup 은 소스 저장소 플랫폼의 그룹(네임스페이스)이다.
type SCMPlatform ¶
type SCMPlatform string
SCMPlatform 은 스택이 쓰는 소스 저장소 플랫폼이다.
저장소를 만드는 방법도, 파이프라인 파일 형식도, 토큰을 얻는 경로도 플랫폼마다 다르다. 어댑터를 고른 뒤에도 렌더러까지 이 값이 따라가야 해서 포트로 올린다.
const ( // SCMPlatformGitLab 은 Nullus 가 스택에 직접 설치한 GitLab 이다. SCMPlatformGitLab SCMPlatform = "gitlab" // SCMPlatformGitHub 은 외부 SaaS 인 GitHub(또는 GitHub Enterprise Server)다. SCMPlatformGitHub SCMPlatform = "github" // SCMPlatformGitea 는 스택 안에 설치되는 Gitea 다. GitHub 과 달리 주소가 // 클러스터 내부 서비스 DNS 이고 조직도 우리가 만든다. SCMPlatformGitea SCMPlatform = "gitea" )
type SCMProject ¶
type SCMProject struct {
ID string `json:"id"`
Name string `json:"name"`
FullPath string `json:"full_path"`
WebURL string `json:"web_url"`
HTTPCloneURL string `json:"http_clone_url"`
RegistryURL string `json:"registry_url"`
DefaultBranch string `json:"default_branch"`
// Created 는 이번 호출이 저장소를 새로 만들었는지다.
//
// 스캐폴딩을 덮어쓸지 판단하는 데 쓴다. CommitFiles 는 upsert 라 이미 쓰이던
// 저장소에 다시 커밋하면 CI 가 갱신해 둔 이미지 태그가 초기값으로 되돌아가고,
// 사용자가 고친 Dockerfile·워크플로·매니페스트도 함께 사라진다.
Created bool `json:"created"`
}
SCMProject 는 프로비저닝된 프로젝트다.
RegistryURL 은 이 프로젝트에 종속된 컨테이너 레지스트리 경로다. GitLab 의 Container/Package Registry 는 프로젝트 단위로 존재하므로, 공용 베이스 이미지를 두려면 그것을 소유할 프로젝트가 반드시 필요하다.
type SCMProvisioner ¶
type SCMProvisioner interface {
EnsureGroup(ctx context.Context, spec GroupSpec) (*SCMGroup, error)
EnsureProject(ctx context.Context, spec ProjectSpec) (*SCMProject, error)
// CommitFiles 는 파일이 이미 있으면 갱신한다(upsert).
CommitFiles(ctx context.Context, projectID string, spec CommitSpec) error
// DeleteProject 는 저장소를 지운다. 이미 없으면 성공으로 본다.
//
// 되돌릴 수 없다. 사용자가 명시적으로 요청했을 때만 호출해야 하며,
// 파이프라인 삭제의 기본 동작이어서는 안 된다 — 소스 코드는 사용자 자산이다.
DeleteProject(ctx context.Context, projectID string) error
}
SCMProvisioner 는 소스 저장소 플랫폼에 그룹·프로젝트·파일을 만든다.
Ensure* 는 멱등하다 — 이미 있으면 조회 결과를 그대로 돌려준다. 스택 설치는 여러 번 재시도될 수 있으므로 생성 API 를 그대로 노출하지 않는다.
type SCMTokenIssuer ¶
type SCMTokenIssuer interface {
EnsureToken(ctx context.Context, spec SCMTokenSpec) (string, error)
}
SCMTokenIssuer 는 SCM 플랫폼의 API 토큰을 확보한다.
GitLab 은 PAT 값을 생성 시점에만 돌려주므로, 발급한 값을 시크릿 저장소에 보관하고 이후에는 그것을 재사용한다. 저장된 값이 없을 때만 새로 발급한다.
type SCMTokenSpec ¶
type SCMTokenSpec struct {
// StackID 는 시크릿 저장소를 고르는 키다.
//
// OpenBao 는 스택마다 배포되므로 전역 주소가 하나일 수 없다.
// 스택 범위로 접근해야 해당 스택의 OpenBao 에 저장된다.
StackID string
// ClusterID 는 kubeconfig 를 찾는 키다.
ClusterID string
// Namespace 는 SCM(GitLab)이 설치된 네임스페이스다.
Namespace string
// OrgID / Env 는 시크릿 저장 경로를 구성한다.
OrgID string
Env string
// Force 가 true 면 저장된 토큰을 무시하고 새로 발급한다.
// 토큰이 만료되거나 폐기돼 401 을 받은 호출자가 쓴다.
Force bool
}
SCMTokenSpec 은 SCM API 토큰 확보 요청이다.
type SCMWebhookProvisioner ¶
type SCMWebhookProvisioner interface {
EnsureWebhook(ctx context.Context, projectID, targetURL, secret string) error
}
SCMWebhookProvisioner 는 저장소에 webhook 을 건다.
Jenkins multibranch job 은 스스로 폴링하지 않는 한 새 커밋을 모른다. 폴링은 지연이 크고 리포가 늘수록 부하가 커지므로 push webhook 을 건다.
type StackReader ¶
type StackReader interface {
// GetStackSummary retrieves minimal stack information by ID.
// Returns nil and no error if the stack does not exist.
GetStackSummary(ctx context.Context, stackID string) (*StackSummary, error)
}
StackReader provides read-only access to Stack context data. This is a Port (in Hexagonal Architecture terms) that the CI/CD context uses to validate cross-context references without importing the Stack domain directly.
type StackSummary ¶
type StackSummary struct {
ID string `json:"id"`
OrgID string `json:"org_id"`
ClusterID string `json:"cluster_id"`
State string `json:"state"` // "completed", "failed", etc.
// Name 은 스택 이름이다. 스택이 만든 게이트웨이 이름이 여기서 나온다
// (`<이름>-gateway`). 도메인에서 유추하면 존재하지 않는 이름이 만들어진다.
Name string `json:"name"`
// Namespace 는 스택이 설치된 네임스페이스다. GitLab/Argo CD 의 클러스터 내
// 주소를 만들 때 쓴다.
Namespace string `json:"namespace"`
// SourceRepository / ContainerRegistry 는 스택이 고른 도구 이름이다
// (예: "GitLab CE", "GitLab Registry", "Harbor").
// 이미지 저장 위치를 결정하는 근거가 된다.
SourceRepository string `json:"source_repository"`
ContainerRegistry string `json:"container_registry"`
// AccessDomain 은 스택의 외부 접근 도메인이다. 비어 있을 수 있다.
AccessDomain string `json:"access_domain"`
// OTLPEndpoint 는 스택 OpenTelemetry Collector 의 클러스터 내 주소다
// (host:port). 수집기를 고르지 않은 스택에서는 비어 있다.
//
// 배포되는 앱에 넣어 줄 값이라 CI/CD 가 알아야 하는데, 릴리스명·차트명으로
// 주소를 조립하는 규칙은 Stack 컨텍스트의 것이다. 그래서 조립된 결과만
// 받아 온다 — 여기서 규칙을 흉내 내면 차트가 바뀔 때 조용히 어긋난다.
OTLPEndpoint string `json:"otlp_endpoint"`
}
StackSummary contains the minimal information the CI/CD module needs from the Stack context. This avoids importing stack/domain directly, keeping the Bounded Context boundary intact.