mirror of
https://github.com/holos-run/holos.git
synced 2026-03-07 03:51:00 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a60b613ff | ||
|
|
5862725bab | ||
|
|
8660826b05 | ||
|
|
449df91e33 | ||
|
|
ac59173b30 | ||
|
|
fb75e560fc | ||
|
|
69a064e3ea | ||
|
|
71b72807bb | ||
|
|
0e4ecf9d13 | ||
|
|
ec2fdadd44 | ||
|
|
38b082095f | ||
|
|
f9346ea7c0 | ||
|
|
0f7010288a |
@@ -37,6 +37,7 @@
|
||||
"blackbox",
|
||||
"buildplan",
|
||||
"buildplans",
|
||||
"Buildx",
|
||||
"builtinpluginloadingoptions",
|
||||
"cachedir",
|
||||
"cadvisor",
|
||||
@@ -84,6 +85,7 @@
|
||||
"destinationrules",
|
||||
"devel",
|
||||
"devicecode",
|
||||
"distroless",
|
||||
"dnsmasq",
|
||||
"dscacheutil",
|
||||
"ecrauthorizationtoken",
|
||||
@@ -281,6 +283,7 @@
|
||||
"serviceentries",
|
||||
"serviceentry",
|
||||
"servicemonitor",
|
||||
"sigstore",
|
||||
"somevalue",
|
||||
"SOMEVAR",
|
||||
"sortoptions",
|
||||
@@ -321,6 +324,7 @@
|
||||
"udev",
|
||||
"uibutton",
|
||||
"Unmarshal",
|
||||
"unshallow",
|
||||
"unstage",
|
||||
"untar",
|
||||
"upbound",
|
||||
|
||||
143
.github/workflows/container.yaml
vendored
Normal file
143
.github/workflows/container.yaml
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
name: Container
|
||||
|
||||
# Only allow actors with write permission to the repository to trigger this
|
||||
# workflow.
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
git_ref:
|
||||
description: 'Git ref to build (e.g., refs/tags/v1.2.3, refs/heads/main)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Set tag from trigger event
|
||||
id: opts
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "ref=${{ inputs.git_ref }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "ref=${GITHUB_REF}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ steps.opts.outputs.ref }}
|
||||
- name: SHA
|
||||
id: sha
|
||||
run: echo "sha=$(/usr/bin/git log -1 --format='%H')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Fetch tags
|
||||
run: git fetch --prune --unshallow --tags
|
||||
- name: Set Tags
|
||||
id: tags
|
||||
run: |
|
||||
echo "detail=$(/usr/bin/git describe --tags HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "suffix=$(test -n "$(git status --porcelain)" && echo '-dirty' || echo '')" >> $GITHUB_OUTPUT
|
||||
echo "tag=$(/usr/bin/git describe --tags HEAD)$(test -n "$(git status --porcelain)" && echo '-dirty' || echo '')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login to ghcr.io
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push container images
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/holos-run/holos:${{ steps.tags.outputs.tag }}
|
||||
ghcr.io/holos-run/holos:${{ steps.sha.outputs.sha }}${{ steps.tags.outputs.suffix }}
|
||||
- name: Setup Cosign to sign container images
|
||||
uses: sigstore/cosign-installer@v3.7.0
|
||||
- name: Sign with GitHub OIDC Token
|
||||
env:
|
||||
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||
run: |
|
||||
cosign sign --yes ghcr.io/holos-run/holos:${{ steps.tags.outputs.tag }}@${DIGEST}
|
||||
cosign sign --yes ghcr.io/holos-run/holos:${{ steps.sha.outputs.sha }}${{ steps.tags.outputs.suffix }}@${DIGEST}
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
owner: ${{ github.repository_owner }}
|
||||
app-id: ${{ vars.GORELEASER_APP_ID }}
|
||||
private-key: ${{ secrets.GORELEASER_APP_PRIVATE_KEY }}
|
||||
- name: Get GitHub App User ID
|
||||
id: get-user-id
|
||||
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
- run: |
|
||||
git config --global user.name '${{ steps.app-token.outputs.app-slug }}[bot]'
|
||||
git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com'
|
||||
- name: Update holos-run/holos-action
|
||||
env:
|
||||
IMAGE: ghcr.io/holos-run/holos:v0.102.1
|
||||
VERSION: ${{ steps.tags.outputs.tag }}
|
||||
USER_ID: ${{ steps.get-user-id.outputs.user-id }}
|
||||
TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git clone "https://github.com/holos-run/holos-action"
|
||||
cd holos-action
|
||||
git remote set-url origin https://${USER_ID}:${TOKEN}@github.com/holos-run/holos-action
|
||||
docker pull --quiet "${IMAGE}"
|
||||
docker run -v $(pwd):/app --workdir /app --rm "${IMAGE}" \
|
||||
holos cue export --out yaml action.cue -t "version=${VERSION}" > action.yml
|
||||
git add action.yml
|
||||
git commit -m "ci: update holos to ${VERSION} - https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || (echo "No changes to commit"; exit 0)
|
||||
git push origin HEAD:main HEAD:v0 HEAD:v1
|
||||
|
||||
- name: Login to quay.io
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: quay.io
|
||||
username: ${{ secrets.QUAY_USER }}
|
||||
password: ${{ secrets.QUAY_TOKEN }}
|
||||
- name: Push to quay.io
|
||||
env:
|
||||
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||
run: |
|
||||
# docker push quay.io/holos-run/holos:${{ steps.tags.outputs.tag }}
|
||||
docker pull --quiet ghcr.io/holos-run/holos:${{ steps.tags.outputs.tag }}@${DIGEST}
|
||||
docker tag ghcr.io/holos-run/holos:${{ steps.tags.outputs.tag }}@${DIGEST} \
|
||||
quay.io/holos-run/holos:${{ steps.tags.outputs.tag }}
|
||||
docker push quay.io/holos-run/holos:${{ steps.tags.outputs.tag }}
|
||||
|
||||
docker pull --quiet ghcr.io/holos-run/holos:${{ steps.sha.outputs.sha }}${{ steps.tags.outputs.suffix }}@${DIGEST}
|
||||
docker tag ghcr.io/holos-run/holos:${{ steps.sha.outputs.sha }}${{ steps.tags.outputs.suffix }}@${DIGEST} \
|
||||
quay.io/holos-run/holos:${{ steps.sha.outputs.sha }}${{ steps.tags.outputs.suffix }}
|
||||
docker push quay.io/holos-run/holos:${{ steps.sha.outputs.sha }}${{ steps.tags.outputs.suffix }}
|
||||
- name: Sign quay.io image
|
||||
env:
|
||||
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||
run: |
|
||||
cosign sign --yes quay.io/holos-run/holos:${{ steps.tags.outputs.tag }}@${DIGEST}
|
||||
cosign sign --yes quay.io/holos-run/holos:${{ steps.sha.outputs.sha }}${{ steps.tags.outputs.suffix }}@${DIGEST}
|
||||
|
||||
outputs:
|
||||
tag: ${{ steps.tags.outputs.tag }}
|
||||
detail: ${{ steps.tags.outputs.detail }}
|
||||
39
Dockerfile
39
Dockerfile
@@ -1,8 +1,31 @@
|
||||
FROM quay.io/holos-run/debian:bullseye AS final
|
||||
USER root
|
||||
WORKDIR /app
|
||||
ADD bin bin
|
||||
RUN chown -R app: /app
|
||||
# Kubernetes requires the user to be numeric
|
||||
USER 8192
|
||||
ENTRYPOINT bin/holos server
|
||||
FROM registry.k8s.io/kubectl:v1.31.0 AS kubectl
|
||||
# https://github.com/GoogleContainerTools/distroless
|
||||
FROM golang:1.23 AS build
|
||||
|
||||
WORKDIR /go/src/app
|
||||
COPY . .
|
||||
|
||||
RUN CGO_ENABLED=0 make install
|
||||
RUN CGO_ENABLED=0 go install sigs.k8s.io/kustomize/kustomize/v5
|
||||
|
||||
# Install helm to /usr/local/bin/helm
|
||||
# https://helm.sh/docs/intro/install/#from-script
|
||||
# https://holos.run/docs/v1alpha5/tutorial/setup/#dependencies
|
||||
RUN curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 \
|
||||
&& chmod 700 get_helm.sh \
|
||||
&& DESIRED_VERSION=v3.16.2 ./get_helm.sh \
|
||||
&& rm -f get_helm.sh
|
||||
|
||||
COPY --from=kubectl /bin/kubectl /usr/local/bin/
|
||||
|
||||
# distroless
|
||||
FROM gcr.io/distroless/static-debian12 AS final
|
||||
COPY --from=build \
|
||||
/go/bin/holos \
|
||||
/go/bin/kustomize \
|
||||
/usr/local/bin/kubectl \
|
||||
/usr/local/bin/helm \
|
||||
/bin/
|
||||
|
||||
# Usage: docker run -v $(pwd):/app --workdir /app --rm -it quay.io/holos-run/holos holos render platform
|
||||
CMD ["/bin/holos"]
|
||||
|
||||
@@ -263,7 +263,7 @@ type Metadata struct {
|
||||
// Labels represents a resource selector.
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
// Annotations represents arbitrary non-identifying metadata. For example
|
||||
// holos uses the `cli.holos.run/description` annotation to log resources in a
|
||||
// holos uses the `app.holos.run/description` annotation to log resources in a
|
||||
// user customized way.
|
||||
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
||||
}
|
||||
@@ -320,7 +320,7 @@ type Component struct {
|
||||
// resulting BuildPlan.
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
// Annotations represents arbitrary non-identifying metadata. Use the
|
||||
// `cli.holos.run/description` to customize the log message of each BuildPlan.
|
||||
// `app.holos.run/description` to customize the log message of each BuildPlan.
|
||||
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ type Component struct {
|
||||
// resulting BuildPlan.
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
// Annotations represents arbitrary non-identifying metadata. Use the
|
||||
// `cli.holos.run/description` to customize the log message of each BuildPlan.
|
||||
// `app.holos.run/description` to customize the log message of each BuildPlan.
|
||||
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
||||
}
|
||||
```
|
||||
@@ -376,7 +376,7 @@ type Metadata struct {
|
||||
// Labels represents a resource selector.
|
||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||
// Annotations represents arbitrary non-identifying metadata. For example
|
||||
// holos uses the `cli.holos.run/description` annotation to log resources in a
|
||||
// holos uses the `app.holos.run/description` annotation to log resources in a
|
||||
// user customized way.
|
||||
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
7
go.mod
7
go.mod
@@ -46,6 +46,7 @@ require (
|
||||
k8s.io/client-go v0.31.1
|
||||
k8s.io/kubectl v0.31.1
|
||||
modernc.org/sqlite v1.29.6
|
||||
sigs.k8s.io/kustomize/kustomize/v5 v5.5.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
@@ -354,7 +355,6 @@ require (
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/automaxprocs v1.5.3 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
@@ -394,7 +394,8 @@ require (
|
||||
oras.land/oras-go v1.2.5 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kind v0.23.0 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.17.2 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.18.0 // indirect
|
||||
sigs.k8s.io/kustomize/cmd/config v0.15.0 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
)
|
||||
|
||||
15
go.sum
15
go.sum
@@ -1077,8 +1077,6 @@ go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVf
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
|
||||
@@ -1282,7 +1280,6 @@ golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
@@ -1557,10 +1554,14 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kind v0.23.0 h1:8fyDGWbWTeCcCTwA04v4Nfr45KKxbSPH1WO9K+jVrBg=
|
||||
sigs.k8s.io/kind v0.23.0/go.mod h1:ZQ1iZuJLh3T+O8fzhdi3VWcFTzsdXtNv2ppsHc8JQ7s=
|
||||
sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g=
|
||||
sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
|
||||
sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo=
|
||||
sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U=
|
||||
sigs.k8s.io/kustomize/cmd/config v0.15.0 h1:WkdY8V2+8J+W00YbImXa2ke9oegfrHH79e+kywW7EdU=
|
||||
sigs.k8s.io/kustomize/cmd/config v0.15.0/go.mod h1:Jq57b0nPaoYUlOqg//0JtAh6iibboqMcfbtCYoWPM00=
|
||||
sigs.k8s.io/kustomize/kustomize/v5 v5.5.0 h1:o1mtt6vpxsxDYaZKrw3BnEtc+pAjLz7UffnIvHNbvW0=
|
||||
sigs.k8s.io/kustomize/kustomize/v5 v5.5.0/go.mod h1:AeFCmgCrXzmvjWWaeZCyBp6XzG1Y0w1svYus8GhJEOE=
|
||||
sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E=
|
||||
sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
@@ -19,11 +20,15 @@ import (
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
)
|
||||
|
||||
// cue context and loading is not safe for concurrent use.
|
||||
var cueMutex sync.Mutex
|
||||
|
||||
// ExtractYAML extracts yaml encoded data from file paths. The data is unified
|
||||
// into one [cue.Value]. If a path element is a directory, all files in the
|
||||
// directory are loaded non-recursively.
|
||||
//
|
||||
// Attribution: https://github.com/cue-lang/cue/issues/3504
|
||||
// Deprecated: Use cue embed instead.
|
||||
func ExtractYAML(ctxt *cue.Context, filepaths []string) (cue.Value, error) {
|
||||
value := ctxt.CompileString("")
|
||||
files := make([]string, 0, 10*len(filepaths))
|
||||
@@ -67,6 +72,8 @@ func ExtractYAML(ctxt *cue.Context, filepaths []string) (cue.Value, error) {
|
||||
// extracted data values are unified with the platform configuration [cue.Value]
|
||||
// in the returned [Instance].
|
||||
func LoadInstance(path string, filepaths []string, tags []string) (*Instance, error) {
|
||||
cueMutex.Lock()
|
||||
defer cueMutex.Unlock()
|
||||
root, leaf, err := util.FindRootLeaf(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
@@ -89,7 +96,6 @@ func LoadInstance(path string, filepaths []string, tags []string) (*Instance, er
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
// TODO: https://cuelang.org/docs/howto/place-data-go-api/
|
||||
value = value.Unify(values[0])
|
||||
|
||||
inst := &Instance{
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// platform.
|
||||
type PlatformOpts struct {
|
||||
Fn func(context.Context, int, holos.Component) error
|
||||
Selector holos.Selector
|
||||
Selectors holos.Selectors
|
||||
Concurrency int
|
||||
InfoEnabled bool
|
||||
}
|
||||
@@ -31,7 +31,7 @@ type Platform struct {
|
||||
func (p *Platform) Build(ctx context.Context, opts PlatformOpts) error {
|
||||
limit := max(opts.Concurrency, 1)
|
||||
parentStart := time.Now()
|
||||
components := p.Select(opts.Selector)
|
||||
components := p.Select(opts.Selectors...)
|
||||
total := len(components)
|
||||
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
@@ -45,8 +45,8 @@ func newPlatform(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
|
||||
cmd.Flags().StringVar(&platform, "platform", "./platform", "platform directory path")
|
||||
var extractYAMLs holos.StringSlice
|
||||
cmd.Flags().Var(&extractYAMLs, "extract-yaml", "data file paths to extract and unify with the platform config")
|
||||
var selector holos.Selector
|
||||
cmd.Flags().VarP(&selector, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
var selectors holos.Selectors
|
||||
cmd.Flags().VarP(&selectors, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
tagMap := make(holos.TagMap)
|
||||
cmd.Flags().VarP(&tagMap, "inject", "t", tagHelp)
|
||||
|
||||
@@ -75,7 +75,7 @@ func newPlatform(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
|
||||
}
|
||||
opts := builder.PlatformOpts{
|
||||
Fn: makeComponentRenderFunc(cmd.ErrOrStderr(), prefixArgs, tagMap.Tags()),
|
||||
Selector: selector,
|
||||
Selectors: selectors,
|
||||
Concurrency: concurrency,
|
||||
InfoEnabled: true,
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ func newShowBuildPlanCmd() (cmd *cobra.Command) {
|
||||
cmd.Flags().Var(&extractYAMLs, "extract-yaml", "data file paths to extract and unify with the platform config")
|
||||
var format string
|
||||
cmd.Flags().StringVar(&format, "format", "yaml", "yaml or json format")
|
||||
var selector holos.Selector
|
||||
cmd.Flags().VarP(&selector, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
var selectors holos.Selectors
|
||||
cmd.Flags().VarP(&selectors, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
tagMap := make(holos.TagMap)
|
||||
cmd.Flags().VarP(&tagMap, "inject", "t", "set the value of a cue @tag field from a key=value pair")
|
||||
var concurrency int
|
||||
@@ -102,7 +102,7 @@ func newShowBuildPlanCmd() (cmd *cobra.Command) {
|
||||
|
||||
platformOpts := builder.PlatformOpts{
|
||||
Fn: makeBuildFunc(encoder, buildPlanOpts),
|
||||
Selector: selector,
|
||||
Selectors: selectors,
|
||||
Concurrency: concurrency,
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ package core
|
||||
labels?: {[string]: string} @go(Labels,map[string]string)
|
||||
|
||||
// Annotations represents arbitrary non-identifying metadata. For example
|
||||
// holos uses the `cli.holos.run/description` annotation to log resources in a
|
||||
// holos uses the `app.holos.run/description` annotation to log resources in a
|
||||
// user customized way.
|
||||
annotations?: {[string]: string} @go(Annotations,map[string]string)
|
||||
}
|
||||
@@ -355,7 +355,7 @@ package core
|
||||
labels?: {[string]: string} @go(Labels,map[string]string)
|
||||
|
||||
// Annotations represents arbitrary non-identifying metadata. Use the
|
||||
// `cli.holos.run/description` to customize the log message of each BuildPlan.
|
||||
// `app.holos.run/description` to customize the log message of each BuildPlan.
|
||||
annotations?: {[string]: string} @go(Annotations,map[string]string)
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,28 @@ func (e *EnvFlagger) Flag(name feature) bool {
|
||||
|
||||
type Labels map[string]string
|
||||
|
||||
type Selectors []Selector
|
||||
|
||||
// String implements the flag.Value interface.
|
||||
func (s *Selectors) String() string {
|
||||
return fmt.Sprint(*s)
|
||||
}
|
||||
|
||||
// Type implements the pflag.Value interface and describes the type.
|
||||
func (s *Selectors) Type() string {
|
||||
return "selectors"
|
||||
}
|
||||
|
||||
// Set implements the flag.Value interface.
|
||||
func (s *Selectors) Set(value string) error {
|
||||
selector := Selector{}
|
||||
if err := selector.Set(value); err != nil {
|
||||
return err
|
||||
}
|
||||
*s = append(*s, selector)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Selector struct {
|
||||
Positive map[string]string
|
||||
Negative map[string]string
|
||||
@@ -118,14 +140,9 @@ func (s *Selector) IsSelected(labels Labels) bool {
|
||||
return true // Nil selector selects everything
|
||||
}
|
||||
|
||||
if len(s.Positive) == 0 && len(s.Negative) == 0 {
|
||||
return true // Empty selector selects everything
|
||||
}
|
||||
|
||||
// Check positive matches
|
||||
for k, v := range s.Positive {
|
||||
val, ok := labels[k]
|
||||
if !ok || v != val {
|
||||
if val, ok := labels[k]; !ok || v != val {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -251,15 +268,18 @@ func (y *yamlEncoder) Close() error {
|
||||
return errors.Wrap(y.enc.Close())
|
||||
}
|
||||
|
||||
// IsSelected returns true if all selectors select the given labels or no
|
||||
// IsSelected returns true if any one selector selects the given labels or no
|
||||
// selectors are given.
|
||||
func IsSelected(labels Labels, selectors ...Selector) bool {
|
||||
if len(selectors) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, selector := range selectors {
|
||||
if !selector.IsSelected(labels) {
|
||||
return false
|
||||
if selector.IsSelected(labels) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
type orderedEncoder struct {
|
||||
|
||||
@@ -6,6 +6,7 @@ package tools
|
||||
// https://go.dev/wiki/Modules
|
||||
|
||||
import (
|
||||
_ "sigs.k8s.io/kustomize/kustomize/v5"
|
||||
_ "connectrpc.com/connect/cmd/protoc-gen-connect-go"
|
||||
_ "cuelang.org/go/cmd/cue"
|
||||
_ "github.com/bufbuild/buf/cmd/buf"
|
||||
|
||||
@@ -1 +1 @@
|
||||
0
|
||||
4
|
||||
|
||||
Reference in New Issue
Block a user