mirror of
https://github.com/cozystack/cozystack.git
synced 2026-03-12 09:58:58 +00:00
Compare commits
6 Commits
feat/cozys
...
feat/cozyc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
488b1bf27b | ||
|
|
f4e9660b43 | ||
|
|
d9cfd5ac9e | ||
|
|
5762ac4139 | ||
|
|
38f446c0d3 | ||
|
|
4de8e91864 |
15
Makefile
15
Makefile
@@ -58,7 +58,10 @@ manifests:
|
||||
cozypkg:
|
||||
go build -ldflags "-X github.com/cozystack/cozystack/cmd/cozypkg/cmd.Version=v$(COZYSTACK_VERSION)" -o _out/bin/cozypkg ./cmd/cozypkg
|
||||
|
||||
assets: assets-talos assets-cozypkg
|
||||
cozyctl:
|
||||
go build -ldflags "-X github.com/cozystack/cozystack/cmd/cozyctl/cmd.Version=v$(COZYSTACK_VERSION)" -o _out/bin/cozyctl ./cmd/cozyctl
|
||||
|
||||
assets: assets-talos assets-cozypkg assets-cozyctl
|
||||
|
||||
assets-talos:
|
||||
make -C packages/core/talos assets
|
||||
@@ -73,6 +76,16 @@ assets-cozypkg-%:
|
||||
cp LICENSE _out/bin/cozypkg-$*/LICENSE
|
||||
tar -C _out/bin/cozypkg-$* -czf _out/assets/cozypkg-$*.tar.gz LICENSE cozypkg$(EXT)
|
||||
|
||||
assets-cozyctl: assets-cozyctl-linux-amd64 assets-cozyctl-linux-arm64 assets-cozyctl-darwin-amd64 assets-cozyctl-darwin-arm64 assets-cozyctl-windows-amd64 assets-cozyctl-windows-arm64
|
||||
(cd _out/assets/ && sha256sum cozyctl-*.tar.gz) > _out/assets/cozyctl-checksums.txt
|
||||
|
||||
assets-cozyctl-%:
|
||||
$(eval EXT := $(if $(filter windows,$(firstword $(subst -, ,$*))),.exe,))
|
||||
mkdir -p _out/assets
|
||||
GOOS=$(firstword $(subst -, ,$*)) GOARCH=$(lastword $(subst -, ,$*)) go build -ldflags "-X github.com/cozystack/cozystack/cmd/cozyctl/cmd.Version=v$(COZYSTACK_VERSION)" -o _out/bin/cozyctl-$*/cozyctl$(EXT) ./cmd/cozyctl
|
||||
cp LICENSE _out/bin/cozyctl-$*/LICENSE
|
||||
tar -C _out/bin/cozyctl-$* -czf _out/assets/cozyctl-$*.tar.gz LICENSE cozyctl$(EXT)
|
||||
|
||||
test:
|
||||
make -C packages/core/testing apply
|
||||
make -C packages/core/testing test
|
||||
|
||||
114
cmd/cozyctl/cmd/client.go
Normal file
114
cmd/cozyctl/cmd/client.go
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/dynamic"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func buildRestConfig() (*rest.Config, error) {
|
||||
rules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
if globalFlags.kubeconfig != "" {
|
||||
rules.ExplicitPath = globalFlags.kubeconfig
|
||||
}
|
||||
overrides := &clientcmd.ConfigOverrides{}
|
||||
if globalFlags.context != "" {
|
||||
overrides.CurrentContext = globalFlags.context
|
||||
}
|
||||
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load kubeconfig: %w", err)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func newScheme() *runtime.Scheme {
|
||||
scheme := runtime.NewScheme()
|
||||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
utilruntime.Must(cozyv1alpha1.AddToScheme(scheme))
|
||||
return scheme
|
||||
}
|
||||
|
||||
func newClients() (client.Client, dynamic.Interface, error) {
|
||||
config, err := buildRestConfig()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
scheme := newScheme()
|
||||
|
||||
typedClient, err := client.New(config, client.Options{Scheme: scheme})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create k8s client: %w", err)
|
||||
}
|
||||
|
||||
dynClient, err := dynamic.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create dynamic client: %w", err)
|
||||
}
|
||||
|
||||
return typedClient, dynClient, nil
|
||||
}
|
||||
|
||||
func getNamespace() (string, error) {
|
||||
if globalFlags.namespace != "" {
|
||||
return globalFlags.namespace, nil
|
||||
}
|
||||
|
||||
rules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
if globalFlags.kubeconfig != "" {
|
||||
rules.ExplicitPath = globalFlags.kubeconfig
|
||||
}
|
||||
overrides := &clientcmd.ConfigOverrides{}
|
||||
if globalFlags.context != "" {
|
||||
overrides.CurrentContext = globalFlags.context
|
||||
}
|
||||
|
||||
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides)
|
||||
ns, _, err := clientConfig.Namespace()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to determine namespace: %w", err)
|
||||
}
|
||||
if ns == "" {
|
||||
ns = "default"
|
||||
}
|
||||
return ns, nil
|
||||
}
|
||||
|
||||
// getRestConfig is a convenience function when only the rest.Config is needed
|
||||
// (used by buildRestConfig but also available for other callers).
|
||||
func getRestConfig() (*rest.Config, error) {
|
||||
if globalFlags.kubeconfig != "" || globalFlags.context != "" {
|
||||
return buildRestConfig()
|
||||
}
|
||||
config, err := ctrl.GetConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get kubeconfig: %w", err)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
43
cmd/cozyctl/cmd/console.go
Normal file
43
cmd/cozyctl/cmd/console.go
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var consoleCmd = &cobra.Command{
|
||||
Use: "console <type> <name>",
|
||||
Short: "Open a serial console to a VirtualMachine",
|
||||
Long: `Open a serial console to a VirtualMachine using virtctl. Only valid for VirtualMachine or VMInstance kinds.`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: runConsole,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(consoleCmd)
|
||||
}
|
||||
|
||||
func runConsole(cmd *cobra.Command, args []string) error {
|
||||
vmName, ns, err := resolveVMArgs(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
virtctlArgs := []string{"virtctl", "console", vmName, "-n", ns}
|
||||
return execVirtctl(virtctlArgs)
|
||||
}
|
||||
112
cmd/cozyctl/cmd/discovery.go
Normal file
112
cmd/cozyctl/cmd/discovery.go
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// AppDefInfo holds resolved information about an ApplicationDefinition.
|
||||
type AppDefInfo struct {
|
||||
Name string // e.g. "postgres"
|
||||
Kind string // e.g. "Postgres"
|
||||
Plural string // e.g. "postgreses"
|
||||
Singular string // e.g. "postgres"
|
||||
Prefix string // e.g. "postgres-"
|
||||
IsModule bool
|
||||
}
|
||||
|
||||
// AppDefRegistry provides fast lookup of ApplicationDefinitions by plural, singular, or kind.
|
||||
type AppDefRegistry struct {
|
||||
byPlural map[string]*AppDefInfo
|
||||
bySingular map[string]*AppDefInfo
|
||||
byKind map[string]*AppDefInfo
|
||||
all []*AppDefInfo
|
||||
}
|
||||
|
||||
// discoverAppDefs lists all ApplicationDefinitions from the cluster and builds a registry.
|
||||
func discoverAppDefs(ctx context.Context, typedClient client.Client) (*AppDefRegistry, error) {
|
||||
var list cozyv1alpha1.ApplicationDefinitionList
|
||||
if err := typedClient.List(ctx, &list); err != nil {
|
||||
return nil, fmt.Errorf("failed to list ApplicationDefinitions: %w", err)
|
||||
}
|
||||
|
||||
reg := &AppDefRegistry{
|
||||
byPlural: make(map[string]*AppDefInfo),
|
||||
bySingular: make(map[string]*AppDefInfo),
|
||||
byKind: make(map[string]*AppDefInfo),
|
||||
}
|
||||
|
||||
for i := range list.Items {
|
||||
ad := &list.Items[i]
|
||||
info := &AppDefInfo{
|
||||
Name: ad.Name,
|
||||
Kind: ad.Spec.Application.Kind,
|
||||
Plural: ad.Spec.Application.Plural,
|
||||
Singular: ad.Spec.Application.Singular,
|
||||
Prefix: ad.Spec.Release.Prefix,
|
||||
IsModule: ad.Spec.Dashboard != nil && ad.Spec.Dashboard.Module,
|
||||
}
|
||||
reg.all = append(reg.all, info)
|
||||
reg.byPlural[strings.ToLower(info.Plural)] = info
|
||||
reg.bySingular[strings.ToLower(info.Singular)] = info
|
||||
reg.byKind[strings.ToLower(info.Kind)] = info
|
||||
}
|
||||
|
||||
return reg, nil
|
||||
}
|
||||
|
||||
// Resolve looks up an AppDefInfo by name (case-insensitive), checking plural, singular, then kind.
|
||||
func (r *AppDefRegistry) Resolve(name string) *AppDefInfo {
|
||||
lower := strings.ToLower(name)
|
||||
if info, ok := r.byPlural[lower]; ok {
|
||||
return info
|
||||
}
|
||||
if info, ok := r.bySingular[lower]; ok {
|
||||
return info
|
||||
}
|
||||
if info, ok := r.byKind[lower]; ok {
|
||||
return info
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResolveModule looks up an AppDefInfo among modules only.
|
||||
func (r *AppDefRegistry) ResolveModule(name string) *AppDefInfo {
|
||||
lower := strings.ToLower(name)
|
||||
for _, info := range r.all {
|
||||
if !info.IsModule {
|
||||
continue
|
||||
}
|
||||
if strings.ToLower(info.Plural) == lower ||
|
||||
strings.ToLower(info.Singular) == lower ||
|
||||
strings.ToLower(info.Kind) == lower {
|
||||
return info
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// All returns all discovered AppDefInfo entries.
|
||||
func (r *AppDefRegistry) All() []*AppDefInfo {
|
||||
return r.all
|
||||
}
|
||||
361
cmd/cozyctl/cmd/get.go
Normal file
361
cmd/cozyctl/cmd/get.go
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
appsv1alpha1 "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1"
|
||||
corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
var getCmdFlags struct {
|
||||
target string
|
||||
}
|
||||
|
||||
var getCmd = &cobra.Command{
|
||||
Use: "get <type> [name]",
|
||||
Short: "Display one or many resources",
|
||||
Long: `Display one or many resources.
|
||||
|
||||
Built-in types:
|
||||
ns, namespaces Tenant namespaces (cluster-scoped)
|
||||
modules Tenant modules
|
||||
pvc, pvcs PersistentVolumeClaims
|
||||
|
||||
Sub-resource types (use -t to filter by parent application):
|
||||
secrets Secrets
|
||||
services, svc Services
|
||||
ingresses, ing Ingresses
|
||||
workloads WorkloadMonitors
|
||||
|
||||
Application types are discovered dynamically from ApplicationDefinitions.
|
||||
Use -t type/name to filter sub-resources by a specific application.`,
|
||||
Args: cobra.RangeArgs(1, 2),
|
||||
RunE: runGet,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(getCmd)
|
||||
getCmd.Flags().StringVarP(&getCmdFlags.target, "target", "t", "", "Filter sub-resources by application type/name")
|
||||
}
|
||||
|
||||
func runGet(cmd *cobra.Command, args []string) error {
|
||||
ctx := context.Background()
|
||||
resourceType := args[0]
|
||||
var resourceName string
|
||||
if len(args) > 1 {
|
||||
resourceName = args[1]
|
||||
}
|
||||
|
||||
switch strings.ToLower(resourceType) {
|
||||
case "ns", "namespace", "namespaces":
|
||||
return getNamespaces(ctx, resourceName)
|
||||
case "module", "modules":
|
||||
return getModules(ctx, resourceName)
|
||||
case "pvc", "pvcs", "persistentvolumeclaim", "persistentvolumeclaims":
|
||||
return getPVCs(ctx, resourceName)
|
||||
case "secret", "secrets":
|
||||
return getSubResources(ctx, "secrets", resourceName)
|
||||
case "service", "services", "svc":
|
||||
return getSubResources(ctx, "services", resourceName)
|
||||
case "ingress", "ingresses", "ing":
|
||||
return getSubResources(ctx, "ingresses", resourceName)
|
||||
case "workload", "workloads":
|
||||
return getSubResources(ctx, "workloads", resourceName)
|
||||
default:
|
||||
return getApplications(ctx, resourceType, resourceName)
|
||||
}
|
||||
}
|
||||
|
||||
func getNamespaces(ctx context.Context, name string) error {
|
||||
_, dynClient, err := newClients()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gvr := schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantnamespaces"}
|
||||
|
||||
if name != "" {
|
||||
item, err := dynClient.Resource(gvr).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get namespace %q: %w", name, err)
|
||||
}
|
||||
printNamespaces([]unstructured.Unstructured{*item})
|
||||
return nil
|
||||
}
|
||||
|
||||
list, err := dynClient.Resource(gvr).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list namespaces: %w", err)
|
||||
}
|
||||
if len(list.Items) == 0 {
|
||||
printNoResources(os.Stderr, "namespaces")
|
||||
return nil
|
||||
}
|
||||
printNamespaces(list.Items)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getModules(ctx context.Context, name string) error {
|
||||
_, dynClient, err := newClients()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ns, err := getNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gvr := schema.GroupVersionResource{Group: "core.cozystack.io", Version: "v1alpha1", Resource: "tenantmodules"}
|
||||
|
||||
if name != "" {
|
||||
item, err := dynClient.Resource(gvr).Namespace(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get module %q: %w", name, err)
|
||||
}
|
||||
printModules([]unstructured.Unstructured{*item})
|
||||
return nil
|
||||
}
|
||||
|
||||
list, err := dynClient.Resource(gvr).Namespace(ns).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list modules: %w", err)
|
||||
}
|
||||
if len(list.Items) == 0 {
|
||||
printNoResources(os.Stderr, "modules")
|
||||
return nil
|
||||
}
|
||||
printModules(list.Items)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPVCs(ctx context.Context, name string) error {
|
||||
_, dynClient, err := newClients()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ns, err := getNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gvr := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}
|
||||
|
||||
if name != "" {
|
||||
item, err := dynClient.Resource(gvr).Namespace(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get PVC %q: %w", name, err)
|
||||
}
|
||||
printPVCs([]unstructured.Unstructured{*item})
|
||||
return nil
|
||||
}
|
||||
|
||||
list, err := dynClient.Resource(gvr).Namespace(ns).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list PVCs: %w", err)
|
||||
}
|
||||
if len(list.Items) == 0 {
|
||||
printNoResources(os.Stderr, "PVCs")
|
||||
return nil
|
||||
}
|
||||
printPVCs(list.Items)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSubResources(ctx context.Context, subType string, name string) error {
|
||||
typedClient, dynClient, err := newClients()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ns, err := getNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
labelSelector, err := buildSubResourceSelector(ctx, typedClient, getCmdFlags.target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch subType {
|
||||
case "secrets":
|
||||
return getFilteredSecrets(ctx, dynClient, ns, name, labelSelector)
|
||||
case "services":
|
||||
return getFilteredServices(ctx, dynClient, ns, name, labelSelector)
|
||||
case "ingresses":
|
||||
return getFilteredIngresses(ctx, dynClient, ns, name, labelSelector)
|
||||
case "workloads":
|
||||
return getFilteredWorkloads(ctx, dynClient, ns, name, labelSelector)
|
||||
default:
|
||||
return fmt.Errorf("unknown sub-resource type: %s", subType)
|
||||
}
|
||||
}
|
||||
|
||||
func buildSubResourceSelector(ctx context.Context, typedClient client.Client, target string) (string, error) {
|
||||
var selectors []string
|
||||
|
||||
if target == "" {
|
||||
selectors = append(selectors, corev1alpha1.TenantResourceLabelKey+"="+corev1alpha1.TenantResourceLabelValue)
|
||||
return strings.Join(selectors, ","), nil
|
||||
}
|
||||
|
||||
parts := strings.SplitN(target, "/", 2)
|
||||
if len(parts) != 2 {
|
||||
return "", fmt.Errorf("invalid target format %q, expected type/name", target)
|
||||
}
|
||||
targetType, targetName := parts[0], parts[1]
|
||||
|
||||
// Discover ApplicationDefinitions to resolve the target type
|
||||
registry, err := discoverAppDefs(ctx, typedClient)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check if this is a module reference
|
||||
if strings.ToLower(targetType) == "module" {
|
||||
info := registry.ResolveModule(targetName)
|
||||
if info == nil {
|
||||
return "", fmt.Errorf("unknown module %q", targetName)
|
||||
}
|
||||
selectors = append(selectors,
|
||||
appsv1alpha1.ApplicationKindLabel+"="+info.Kind,
|
||||
appsv1alpha1.ApplicationNameLabel+"="+targetName,
|
||||
corev1alpha1.TenantResourceLabelKey+"="+corev1alpha1.TenantResourceLabelValue,
|
||||
)
|
||||
return strings.Join(selectors, ","), nil
|
||||
}
|
||||
|
||||
info := registry.Resolve(targetType)
|
||||
if info == nil {
|
||||
return "", fmt.Errorf("unknown application type %q", targetType)
|
||||
}
|
||||
|
||||
selectors = append(selectors,
|
||||
appsv1alpha1.ApplicationKindLabel+"="+info.Kind,
|
||||
appsv1alpha1.ApplicationNameLabel+"="+targetName,
|
||||
corev1alpha1.TenantResourceLabelKey+"="+corev1alpha1.TenantResourceLabelValue,
|
||||
)
|
||||
return strings.Join(selectors, ","), nil
|
||||
}
|
||||
|
||||
func getFilteredSecrets(ctx context.Context, dynClient dynamic.Interface, ns, name, labelSelector string) error {
|
||||
gvr := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}
|
||||
return getFilteredResources(ctx, dynClient, gvr, ns, name, labelSelector, "secrets", printSecrets)
|
||||
}
|
||||
|
||||
func getFilteredServices(ctx context.Context, dynClient dynamic.Interface, ns, name, labelSelector string) error {
|
||||
gvr := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}
|
||||
return getFilteredResources(ctx, dynClient, gvr, ns, name, labelSelector, "services", printServices)
|
||||
}
|
||||
|
||||
func getFilteredIngresses(ctx context.Context, dynClient dynamic.Interface, ns, name, labelSelector string) error {
|
||||
gvr := schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "ingresses"}
|
||||
return getFilteredResources(ctx, dynClient, gvr, ns, name, labelSelector, "ingresses", printIngresses)
|
||||
}
|
||||
|
||||
func getFilteredWorkloads(ctx context.Context, dynClient dynamic.Interface, ns, name, labelSelector string) error {
|
||||
gvr := schema.GroupVersionResource{Group: "cozystack.io", Version: "v1alpha1", Resource: "workloadmonitors"}
|
||||
return getFilteredResources(ctx, dynClient, gvr, ns, name, labelSelector, "workloads", printWorkloads)
|
||||
}
|
||||
|
||||
func getFilteredResources(
|
||||
ctx context.Context,
|
||||
dynClient dynamic.Interface,
|
||||
gvr schema.GroupVersionResource,
|
||||
ns, name, labelSelector string,
|
||||
typeName string,
|
||||
printer func([]unstructured.Unstructured),
|
||||
) error {
|
||||
if name != "" {
|
||||
item, err := dynClient.Resource(gvr).Namespace(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %s %q: %w", typeName, name, err)
|
||||
}
|
||||
printer([]unstructured.Unstructured{*item})
|
||||
return nil
|
||||
}
|
||||
|
||||
list, err := dynClient.Resource(gvr).Namespace(ns).List(ctx, metav1.ListOptions{
|
||||
LabelSelector: labelSelector,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list %s: %w", typeName, err)
|
||||
}
|
||||
if len(list.Items) == 0 {
|
||||
printNoResources(os.Stderr, typeName)
|
||||
return nil
|
||||
}
|
||||
printer(list.Items)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getApplications(ctx context.Context, resourceType, name string) error {
|
||||
typedClient, dynClient, err := newClients()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ns, err := getNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
registry, err := discoverAppDefs(ctx, typedClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info := registry.Resolve(resourceType)
|
||||
if info == nil {
|
||||
return fmt.Errorf("unknown resource type %q\nUse 'cozyctl get --help' for available types", resourceType)
|
||||
}
|
||||
|
||||
gvr := schema.GroupVersionResource{Group: "apps.cozystack.io", Version: "v1alpha1", Resource: info.Plural}
|
||||
|
||||
if name != "" {
|
||||
item, err := dynClient.Resource(gvr).Namespace(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %s %q: %w", info.Singular, name, err)
|
||||
}
|
||||
printApplications([]unstructured.Unstructured{*item})
|
||||
return nil
|
||||
}
|
||||
|
||||
list, err := dynClient.Resource(gvr).Namespace(ns).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list %s: %w", info.Plural, err)
|
||||
}
|
||||
if len(list.Items) == 0 {
|
||||
printNoResources(os.Stderr, info.Plural)
|
||||
return nil
|
||||
}
|
||||
printApplications(list.Items)
|
||||
return nil
|
||||
}
|
||||
43
cmd/cozyctl/cmd/migrate.go
Normal file
43
cmd/cozyctl/cmd/migrate.go
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var migrateCmd = &cobra.Command{
|
||||
Use: "migrate <type> <name>",
|
||||
Short: "Live-migrate a VirtualMachine to another node",
|
||||
Long: `Live-migrate a VirtualMachine to another node using virtctl. Only valid for VirtualMachine or VMInstance kinds.`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: runMigrate,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(migrateCmd)
|
||||
}
|
||||
|
||||
func runMigrate(cmd *cobra.Command, args []string) error {
|
||||
vmName, ns, err := resolveVMArgs(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
virtctlArgs := []string{"virtctl", "migrate", vmName, "-n", ns}
|
||||
return execVirtctl(virtctlArgs)
|
||||
}
|
||||
51
cmd/cozyctl/cmd/portforward.go
Normal file
51
cmd/cozyctl/cmd/portforward.go
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var portForwardCmd = &cobra.Command{
|
||||
Use: "port-forward <type/name> [ports...]",
|
||||
Short: "Forward ports to a VirtualMachineInstance",
|
||||
Long: `Forward ports to a VirtualMachineInstance using virtctl. Only valid for VirtualMachine or VMInstance kinds.`,
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
RunE: runPortForward,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(portForwardCmd)
|
||||
}
|
||||
|
||||
func runPortForward(cmd *cobra.Command, args []string) error {
|
||||
vmName, ns, err := resolveVMArgs(args[:1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ports := args[1:]
|
||||
if len(ports) == 0 {
|
||||
return fmt.Errorf("at least one port is required")
|
||||
}
|
||||
|
||||
virtctlArgs := []string{"virtctl", "port-forward", "vmi/" + vmName, "-n", ns}
|
||||
virtctlArgs = append(virtctlArgs, ports...)
|
||||
return execVirtctl(virtctlArgs)
|
||||
}
|
||||
250
cmd/cozyctl/cmd/printer.go
Normal file
250
cmd/cozyctl/cmd/printer.go
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func newTabWriter() *tabwriter.Writer {
|
||||
return tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
}
|
||||
|
||||
func printApplications(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME\tVERSION\tREADY\tSTATUS")
|
||||
for _, item := range items {
|
||||
name := item.GetName()
|
||||
version, _, _ := unstructured.NestedString(item.Object, "appVersion")
|
||||
ready, status := extractCondition(item)
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", name, version, ready, truncate(status, 48))
|
||||
}
|
||||
}
|
||||
|
||||
func printNamespaces(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME")
|
||||
for _, item := range items {
|
||||
fmt.Fprintln(w, item.GetName())
|
||||
}
|
||||
}
|
||||
|
||||
func printModules(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME\tVERSION\tREADY\tSTATUS")
|
||||
for _, item := range items {
|
||||
name := item.GetName()
|
||||
version, _, _ := unstructured.NestedString(item.Object, "appVersion")
|
||||
ready, status := extractCondition(item)
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", name, version, ready, truncate(status, 48))
|
||||
}
|
||||
}
|
||||
|
||||
func printPVCs(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME\tSTATUS\tVOLUME\tCAPACITY\tSTORAGECLASS")
|
||||
for _, item := range items {
|
||||
name := item.GetName()
|
||||
phase, _, _ := unstructured.NestedString(item.Object, "status", "phase")
|
||||
volume, _, _ := unstructured.NestedString(item.Object, "spec", "volumeName")
|
||||
capacity := ""
|
||||
if cap, ok, _ := unstructured.NestedStringMap(item.Object, "status", "capacity"); ok {
|
||||
capacity = cap["storage"]
|
||||
}
|
||||
sc, _, _ := unstructured.NestedString(item.Object, "spec", "storageClassName")
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", name, phase, volume, capacity, sc)
|
||||
}
|
||||
}
|
||||
|
||||
func printSecrets(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME\tTYPE\tDATA")
|
||||
for _, item := range items {
|
||||
name := item.GetName()
|
||||
secretType, _, _ := unstructured.NestedString(item.Object, "type")
|
||||
data, _, _ := unstructured.NestedMap(item.Object, "data")
|
||||
fmt.Fprintf(w, "%s\t%s\t%d\n", name, secretType, len(data))
|
||||
}
|
||||
}
|
||||
|
||||
func printServices(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME\tTYPE\tCLUSTER-IP\tEXTERNAL-IP\tPORTS")
|
||||
for _, item := range items {
|
||||
name := item.GetName()
|
||||
svcType, _, _ := unstructured.NestedString(item.Object, "spec", "type")
|
||||
clusterIP, _, _ := unstructured.NestedString(item.Object, "spec", "clusterIP")
|
||||
|
||||
externalIP := "<none>"
|
||||
if lbIngress, ok, _ := unstructured.NestedSlice(item.Object, "status", "loadBalancer", "ingress"); ok && len(lbIngress) > 0 {
|
||||
var ips []string
|
||||
for _, ingress := range lbIngress {
|
||||
if m, ok := ingress.(map[string]interface{}); ok {
|
||||
if ip, ok := m["ip"].(string); ok {
|
||||
ips = append(ips, ip)
|
||||
} else if hostname, ok := m["hostname"].(string); ok {
|
||||
ips = append(ips, hostname)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ips) > 0 {
|
||||
externalIP = strings.Join(ips, ",")
|
||||
}
|
||||
}
|
||||
|
||||
ports := formatPorts(item)
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", name, svcType, clusterIP, externalIP, ports)
|
||||
}
|
||||
}
|
||||
|
||||
func printIngresses(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME\tCLASS\tHOSTS\tADDRESS")
|
||||
for _, item := range items {
|
||||
name := item.GetName()
|
||||
class, _, _ := unstructured.NestedString(item.Object, "spec", "ingressClassName")
|
||||
|
||||
var hosts []string
|
||||
if rules, ok, _ := unstructured.NestedSlice(item.Object, "spec", "rules"); ok {
|
||||
for _, rule := range rules {
|
||||
if m, ok := rule.(map[string]interface{}); ok {
|
||||
if host, ok := m["host"].(string); ok {
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hostsStr := "<none>"
|
||||
if len(hosts) > 0 {
|
||||
hostsStr = strings.Join(hosts, ",")
|
||||
}
|
||||
|
||||
address := ""
|
||||
if lbIngress, ok, _ := unstructured.NestedSlice(item.Object, "status", "loadBalancer", "ingress"); ok && len(lbIngress) > 0 {
|
||||
var addrs []string
|
||||
for _, ingress := range lbIngress {
|
||||
if m, ok := ingress.(map[string]interface{}); ok {
|
||||
if ip, ok := m["ip"].(string); ok {
|
||||
addrs = append(addrs, ip)
|
||||
} else if hostname, ok := m["hostname"].(string); ok {
|
||||
addrs = append(addrs, hostname)
|
||||
}
|
||||
}
|
||||
}
|
||||
address = strings.Join(addrs, ",")
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", name, class, hostsStr, address)
|
||||
}
|
||||
}
|
||||
|
||||
func printWorkloads(items []unstructured.Unstructured) {
|
||||
w := newTabWriter()
|
||||
defer w.Flush()
|
||||
|
||||
fmt.Fprintln(w, "NAME\tKIND\tTYPE\tVERSION\tAVAILABLE\tOBSERVED\tOPERATIONAL")
|
||||
for _, item := range items {
|
||||
name := item.GetName()
|
||||
kind, _, _ := unstructured.NestedString(item.Object, "spec", "kind")
|
||||
wType, _, _ := unstructured.NestedString(item.Object, "spec", "type")
|
||||
version, _, _ := unstructured.NestedString(item.Object, "spec", "version")
|
||||
available, _, _ := unstructured.NestedInt64(item.Object, "status", "availableReplicas")
|
||||
observed, _, _ := unstructured.NestedInt64(item.Object, "status", "observedReplicas")
|
||||
operational, ok, _ := unstructured.NestedBool(item.Object, "status", "operational")
|
||||
opStr := ""
|
||||
if ok {
|
||||
opStr = fmt.Sprintf("%t", operational)
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\t%d\t%s\n", name, kind, wType, version, available, observed, opStr)
|
||||
}
|
||||
}
|
||||
|
||||
func printNoResources(w io.Writer, resourceType string) {
|
||||
fmt.Fprintf(w, "No %s found\n", resourceType)
|
||||
}
|
||||
|
||||
func extractCondition(item unstructured.Unstructured) (string, string) {
|
||||
conditions, ok, _ := unstructured.NestedSlice(item.Object, "status", "conditions")
|
||||
if !ok {
|
||||
return "Unknown", ""
|
||||
}
|
||||
for _, c := range conditions {
|
||||
cond, ok := c.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if cond["type"] == "Ready" {
|
||||
ready, _ := cond["status"].(string)
|
||||
message, _ := cond["message"].(string)
|
||||
return ready, message
|
||||
}
|
||||
}
|
||||
return "Unknown", ""
|
||||
}
|
||||
|
||||
func truncate(s string, maxLen int) string {
|
||||
if len(s) <= maxLen {
|
||||
return s
|
||||
}
|
||||
return s[:maxLen-3] + "..."
|
||||
}
|
||||
|
||||
func formatPorts(item unstructured.Unstructured) string {
|
||||
ports, ok, _ := unstructured.NestedSlice(item.Object, "spec", "ports")
|
||||
if !ok || len(ports) == 0 {
|
||||
return "<none>"
|
||||
}
|
||||
var parts []string
|
||||
for _, p := range ports {
|
||||
port, ok := p.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
portNum, _, _ := unstructured.NestedInt64(port, "port")
|
||||
protocol, _, _ := unstructured.NestedString(port, "protocol")
|
||||
if protocol == "" {
|
||||
protocol = "TCP"
|
||||
}
|
||||
nodePort, _, _ := unstructured.NestedInt64(port, "nodePort")
|
||||
if nodePort > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%d:%d/%s", portNum, nodePort, protocol))
|
||||
} else {
|
||||
parts = append(parts, fmt.Sprintf("%d/%s", portNum, protocol))
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
57
cmd/cozyctl/cmd/root.go
Normal file
57
cmd/cozyctl/cmd/root.go
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Version is set at build time via -ldflags.
|
||||
var Version = "dev"
|
||||
|
||||
var globalFlags struct {
|
||||
kubeconfig string
|
||||
context string
|
||||
namespace string
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "cozyctl",
|
||||
Short: "A CLI for managing Cozystack applications",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
DisableAutoGenTag: true,
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
func Execute() error {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.Version = Version
|
||||
rootCmd.PersistentFlags().StringVar(&globalFlags.kubeconfig, "kubeconfig", "", "Path to kubeconfig file")
|
||||
rootCmd.PersistentFlags().StringVar(&globalFlags.context, "context", "", "Kubernetes context to use")
|
||||
rootCmd.PersistentFlags().StringVarP(&globalFlags.namespace, "namespace", "n", "", "Kubernetes namespace")
|
||||
}
|
||||
106
cmd/cozyctl/cmd/vm.go
Normal file
106
cmd/cozyctl/cmd/vm.go
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// vmKindPrefix maps application Kind to the release prefix used by KubeVirt VMs.
|
||||
func vmKindPrefix(kind string) (string, bool) {
|
||||
switch kind {
|
||||
case "VirtualMachine":
|
||||
return "virtual-machine", true
|
||||
case "VMInstance":
|
||||
return "vm-instance", true
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
|
||||
// resolveVMArgs takes CLI args (type, name or type/name), resolves the application type
|
||||
// via discovery, validates it's a VM kind, and returns the full VM name and namespace.
|
||||
func resolveVMArgs(args []string) (string, string, error) {
|
||||
var resourceType, resourceName string
|
||||
|
||||
if len(args) == 1 {
|
||||
// type/name format
|
||||
parts := strings.SplitN(args[0], "/", 2)
|
||||
if len(parts) != 2 {
|
||||
return "", "", fmt.Errorf("expected type/name format, got %q", args[0])
|
||||
}
|
||||
resourceType, resourceName = parts[0], parts[1]
|
||||
} else {
|
||||
resourceType = args[0]
|
||||
resourceName = args[1]
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
typedClient, _, err := newClients()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
registry, err := discoverAppDefs(ctx, typedClient)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
info := registry.Resolve(resourceType)
|
||||
if info == nil {
|
||||
return "", "", fmt.Errorf("unknown application type %q", resourceType)
|
||||
}
|
||||
|
||||
prefix, ok := vmKindPrefix(info.Kind)
|
||||
if !ok {
|
||||
return "", "", fmt.Errorf("resource type %q (Kind=%s) is not a VirtualMachine or VMInstance", resourceType, info.Kind)
|
||||
}
|
||||
|
||||
ns, err := getNamespace()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
vmName := prefix + "-" + resourceName
|
||||
return vmName, ns, nil
|
||||
}
|
||||
|
||||
// execVirtctl replaces the current process with virtctl.
|
||||
func execVirtctl(args []string) error {
|
||||
virtctlPath, err := exec.LookPath("virtctl")
|
||||
if err != nil {
|
||||
return fmt.Errorf("virtctl not found in PATH: %w", err)
|
||||
}
|
||||
|
||||
// Append kubeconfig/context flags if set
|
||||
if globalFlags.kubeconfig != "" {
|
||||
args = append(args, "--kubeconfig", globalFlags.kubeconfig)
|
||||
}
|
||||
if globalFlags.context != "" {
|
||||
args = append(args, "--context", globalFlags.context)
|
||||
}
|
||||
|
||||
if err := syscall.Exec(virtctlPath, args, os.Environ()); err != nil {
|
||||
return fmt.Errorf("failed to exec virtctl: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
43
cmd/cozyctl/cmd/vnc.go
Normal file
43
cmd/cozyctl/cmd/vnc.go
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var vncCmd = &cobra.Command{
|
||||
Use: "vnc <type> <name>",
|
||||
Short: "Open a VNC connection to a VirtualMachine",
|
||||
Long: `Open a VNC connection to a VirtualMachine using virtctl. Only valid for VirtualMachine or VMInstance kinds.`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: runVNC,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(vncCmd)
|
||||
}
|
||||
|
||||
func runVNC(cmd *cobra.Command, args []string) error {
|
||||
vmName, ns, err := resolveVMArgs(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
virtctlArgs := []string{"virtctl", "vnc", vmName, "-n", ns}
|
||||
return execVirtctl(virtctlArgs)
|
||||
}
|
||||
29
cmd/cozyctl/main.go
Normal file
29
cmd/cozyctl/main.go
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2025 The Cozystack Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/cozystack/cozystack/cmd/cozyctl/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.40.5
|
||||
-->
|
||||
|
||||
## Improvements
|
||||
|
||||
* **[dashboard] Improve dashboard session params**: Improved session parameter handling in the dashboard for better user experience and more reliable session management ([**@lllamnyp**](https://github.com/lllamnyp) in #1913, #1919).
|
||||
|
||||
## Dependencies
|
||||
|
||||
* **Update cozyhr to v1.6.1**: Updated cozyhr to v1.6.1, which fixes a critical bug causing helm-controller v0.37.0+ to unexpectedly uninstall HelmReleases after cozyhr apply by correcting history snapshot fields for helm-controller compatibility ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr#10).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.40.4...v0.40.5](https://github.com/cozystack/cozystack/compare/v0.40.4...v0.40.5)
|
||||
@@ -1,11 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.40.6
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubernetes] Fix manifests for kubernetes deployment**: Fixed incorrect manifests that prevented proper Kubernetes deployment, restoring correct application behavior ([**@IvanHunters**](https://github.com/IvanHunters) in #1943, #1944).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.40.5...v0.40.6](https://github.com/cozystack/cozystack/compare/v0.40.5...v0.40.6)
|
||||
@@ -1,11 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.40.7
|
||||
-->
|
||||
|
||||
## Security
|
||||
|
||||
* **[dashboard] Verify JWT token**: Added JWT token verification to the dashboard, ensuring that authentication tokens are properly validated before granting access. This prevents unauthorized access through forged or expired tokens ([**@lllamnyp**](https://github.com/lllamnyp) in #1980, #1984).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.40.6...v0.40.7](https://github.com/cozystack/cozystack/compare/v0.40.6...v0.40.7)
|
||||
@@ -1,11 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.4
|
||||
-->
|
||||
|
||||
## Dependencies
|
||||
|
||||
* **Update cozyhr to v1.6.1**: Updated cozyhr to v1.6.1, which fixes a critical bug causing helm-controller v0.37.0+ to unexpectedly uninstall HelmReleases after cozyhr apply by correcting history snapshot fields for helm-controller compatibility ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr#10).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.3...v0.41.4](https://github.com/cozystack/cozystack/compare/v0.41.3...v0.41.4)
|
||||
@@ -1,21 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.5
|
||||
-->
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* **[dashboard] Add "Edit" button to all resources**: Added an "Edit" button across all resource views in the dashboard, allowing users to modify resource configurations directly from the UI ([**@sircthulhu**](https://github.com/sircthulhu) in #1928, #1931).
|
||||
|
||||
* **[dashboard] Add resource quota usage to tenant details page**: Added resource quota usage display to the tenant details page, giving administrators visibility into how much of allocated resources each tenant is consuming ([**@sircthulhu**](https://github.com/sircthulhu) in #1929, #1932).
|
||||
|
||||
* **[branding] Separate values for keycloak**: Separated Keycloak branding values into dedicated configuration, allowing more granular customization of Keycloak appearance without affecting other branding settings ([**@nbykov0**](https://github.com/nbykov0) in #1946).
|
||||
|
||||
* **Add instance profile label to workload monitor**: Added instance profile metadata labels to the workload monitor, enabling better resource tracking and monitoring by instance profile type ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1954, #1957).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubernetes] Fix manifests for kubernetes deployment**: Fixed incorrect manifests that prevented proper Kubernetes deployment, restoring correct application behavior ([**@IvanHunters**](https://github.com/IvanHunters) in #1943, #1945).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.4...v0.41.5](https://github.com/cozystack/cozystack/compare/v0.41.4...v0.41.5)
|
||||
@@ -1,17 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.6
|
||||
-->
|
||||
|
||||
## Improvements
|
||||
|
||||
* **[vm] Allow changing field external after creation**: Users can now modify the external network field on virtual machines after initial creation, providing more flexibility in VM networking configuration without requiring recreation ([**@sircthulhu**](https://github.com/sircthulhu) in #1956, #1962).
|
||||
|
||||
* **[branding] Separate values for keycloak**: Separated Keycloak branding values into dedicated configuration for more granular customization of Keycloak appearance ([**@nbykov0**](https://github.com/nbykov0) in #1947, #1963).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubernetes] Fix coredns serviceaccount to match kubernetes bootstrap RBAC**: Configured the CoreDNS chart to create a `kube-dns` ServiceAccount matching the Kubernetes bootstrap ClusterRoleBinding, fixing RBAC errors (`Failed to watch`) when CoreDNS pods restart ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1958, #1978).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.5...v0.41.6](https://github.com/cozystack/cozystack/compare/v0.41.5...v0.41.6)
|
||||
@@ -1,15 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.7
|
||||
-->
|
||||
|
||||
## Security
|
||||
|
||||
* **[dashboard] Verify JWT token**: Added JWT token verification to the dashboard, ensuring that authentication tokens are properly validated before granting access. This prevents unauthorized access through forged or expired tokens ([**@lllamnyp**](https://github.com/lllamnyp) in #1980, #1983).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[postgres-operator] Correct PromQL syntax in CNPGClusterOffline alert**: Fixed incorrect PromQL syntax in the `CNPGClusterOffline` alert rule for CloudNativePG, ensuring the alert fires correctly when all instances of a PostgreSQL cluster are offline ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1981, #1989).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.6...v0.41.7](https://github.com/cozystack/cozystack/compare/v0.41.6...v0.41.7)
|
||||
@@ -1,17 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.8
|
||||
-->
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* **[kubernetes] Auto-enable Gateway API support in cert-manager**: cert-manager now automatically enables `enableGatewayAPI` when the Gateway API addon is active in the Kubernetes application. Users no longer need to manually configure this setting, and the option can still be overridden via `valuesOverride` ([**@kvaps**](https://github.com/kvaps) in #1997, #2012).
|
||||
|
||||
* **[vm] Allow switching between instancetype and custom resources**: Users can now switch virtual machines between instancetype-based and custom resource configurations after creation. The upgrade hook atomically patches VM resources, providing more flexibility in adjusting VM sizing without recreation ([**@sircthulhu**](https://github.com/sircthulhu) in #2008, #2013).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[dashboard] Add startupProbe to prevent container restarts on slow hardware**: Added `startupProbe` to both `bff` and `web` containers in the dashboard deployment. On slow hardware, kubelet was killing containers because the `livenessProbe` only allowed ~33 seconds for startup. The `startupProbe` gives containers up to 60 seconds to start before `livenessProbe` kicks in ([**@kvaps**](https://github.com/kvaps) in #1996, #2014).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.7...v0.41.8](https://github.com/cozystack/cozystack/compare/v0.41.7...v0.41.8)
|
||||
@@ -1,15 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.41.9
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[cozystack-basics] Deny resourcequotas deletion for tenant admin**: Prevented tenant administrators from deleting resource quotas, ensuring that resource limits set by platform administrators cannot be bypassed by tenant-level users ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2076).
|
||||
|
||||
## Dependencies
|
||||
|
||||
* **Update Kube-OVN to v1.15.3**: Updated Kube-OVN CNI to v1.15.3 with latest bug fixes and improvements ([**@kvaps**](https://github.com/kvaps)).
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.41.8...v0.41.9](https://github.com/cozystack/cozystack/compare/v0.41.8...v0.41.9)
|
||||
@@ -1,65 +0,0 @@
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.0.0-rc.1
|
||||
-->
|
||||
|
||||
> **⚠️ Release Candidate Warning**: This is a release candidate intended for final validation before the stable v1.0.0 release. Breaking changes are not expected at this stage, but please test thoroughly before deploying to production.
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* **[harbor] Add managed Harbor container registry**: Added Harbor v2.14.2 as a managed tenant-level container registry service. The application uses CloudNativePG for PostgreSQL, the Redis operator for caching, and S3 via COSI BucketClaim (from SeaweedFS) for registry image storage. Auto-generated admin credentials are persisted across upgrades, TLS is handled by cert-manager, and Trivy vulnerability scanner is included. Users can now deploy a fully managed, production-ready OCI container registry within their tenant ([**@lexfrei**](https://github.com/lexfrei) in #2058).
|
||||
|
||||
* **[kubernetes] Update supported Kubernetes versions to v1.30–v1.35**: Updated the tenant Kubernetes version matrix to v1.30, v1.31, v1.32, v1.33, v1.34, and v1.35 (now the default). EOL versions v1.28 and v1.29 are removed. Kamaji is updated to edge-26.2.4 with full Kubernetes 1.35 support, and the CAPI Kamaji provider is updated to v0.16.0. A compatibility patch ensures kubelets older than v1.35 are not broken by Kamaji injecting 1.35-specific kubelet fields ([**@lexfrei**](https://github.com/lexfrei) in #2073).
|
||||
|
||||
* **[platform] Make cluster issuer name and ACME solver configurable**: Added `publishing.certificates.solver` (`http01` or `dns01`) and `publishing.certificates.issuerName` (default: `letsencrypt-prod`) parameters to the platform chart. This allows operators to point all ingress TLS annotations at any ClusterIssuer — custom ACME, self-signed, or internal CA — without modifying individual package templates. See the Breaking Changes section for the rename from the previous `issuerType` field ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077).
|
||||
|
||||
* **[dashboard] VMInstance dropdowns for disks and instanceType**: The VM instance creation form now renders API-backed dropdowns for the `instanceType` field (populated from `VirtualMachineClusterInstancetype` cluster resources) and for disk `name` fields (populated from `VMDisk` resources in the same namespace). Default values are read from the ApplicationDefinition's OpenAPI schema. This eliminates manual lookups and reduces misconfiguration when attaching disks or selecting VM instance types ([**@sircthulhu**](https://github.com/sircthulhu) in #2071).
|
||||
|
||||
* **[installer] Remove CRDs from Helm chart, delegate lifecycle to operator**: The `cozy-installer` Helm chart no longer ships CRDs in its `crds/` directory. CRD lifecycle is now fully managed by the Cozystack operator via the `--install-crds` flag, which applies embedded CRD manifests on every startup using server-side apply. The platform PackageSource is also created by the operator instead of a Helm template. This ensures CRDs and the PackageSource are always up to date after each operator restart, eliminating stale CRDs from Helm's install-only behavior ([**@lexfrei**](https://github.com/lexfrei) in #2074).
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[kubevirt] Update KubeVirt to v1.6.4 and CDI to v1.64.0, fix VM pod initialization**: Updated KubeVirt operator to v1.6.4 and CDI operator to v1.64.0, including live migration of existing VMs during the upgrade. Additionally, disabled serial console logging globally via the KubeVirt CR to prevent a known v1.6.x issue ([upstream #15989](https://github.com/kubevirt/kubevirt/issues/15989)) where the `guest-console-log` init container blocked virt-launcher pods from starting, causing all VMs to get stuck in `PodInitializing` state ([**@nbykov0**](https://github.com/nbykov0) in #1833; [**@kvaps**](https://github.com/kvaps) in 7dfb819).
|
||||
|
||||
* **[linstor] Fix DRBD+LUKS+STORAGE resource creation failure**: All newly created encrypted volumes were failing because the DRBD `.res` file was never written due to a missing `setExists(true)` call in the `LuksLayer`. Applied the upstream `skip-adjust-when-device-inaccessible` patch ([LINBIT/linstor-server#477](https://github.com/LINBIT/linstor-server/pull/477)) which fixes the root cause and also prevents unnecessary lsblk calls when devices are not yet physically present ([**@kvaps**](https://github.com/kvaps) in #2072).
|
||||
|
||||
* **[system] Fix monitoring-agents FQDN resolution for tenant workload clusters**: Monitoring agents (`vmagent`, `fluent-bit`) in tenant workload clusters were failing to deliver metrics and logs because service addresses used short DNS names without the cluster domain suffix. Fixed by appending the configured cluster domain from `_cluster.cluster-domain` (with fallback to `cluster.local`) to all vmagent remoteWrite URLs and fluent-bit output hosts ([**@IvanHunters**](https://github.com/IvanHunters) in #2075).
|
||||
|
||||
* **[cozystack-basics] Preserve existing HelmRelease values during reconciliations**: Fixed a data-loss bug where changes made to the `tenant-root` HelmRelease were silently dropped on the next forced or upgrade reconciliation of the `cozystack-basics` HelmRelease. The reconciler now merges new configuration with existing values instead of overwriting them ([**@sircthulhu**](https://github.com/sircthulhu) in #2068).
|
||||
|
||||
* **[cozystack-basics] Deny resourcequotas deletion for tenant admin**: Fixed the `cozy:tenant:admin:base` ClusterRole to explicitly deny deletion of `ResourceQuota` objects for tenant admins and superadmins, preventing accidental removal of tenant resource limits ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2076).
|
||||
|
||||
## Breaking Changes & Upgrade Notes
|
||||
|
||||
* **[platform] Certificate issuer configuration parameters renamed**: The `publishing.certificates.issuerType` field is renamed to `publishing.certificates.solver`, and the value `cloudflare` is renamed to `dns01` to align with standard ACME terminology. A new `publishing.certificates.issuerName` field (default: `letsencrypt-prod`) is introduced to allow pointing all ingresses at a custom ClusterIssuer. Migration 32 is included and automatically converts existing configurations during upgrade — no manual action is required ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077).
|
||||
|
||||
## Documentation
|
||||
|
||||
* **[website] Migrate ConfigMap references to Platform Package in v1 documentation**: Updated the entire v1 documentation tree to replace legacy ConfigMap-based configuration references with the new Platform Package API, ensuring guides are consistent with the v1 configuration model ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#426).
|
||||
|
||||
* **[website] Add generic Kubernetes deployment guide for v1**: Added a new installation guide covering Cozystack deployment on any generic Kubernetes cluster, expanding the set of supported deployment targets beyond provider-specific guides ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#408).
|
||||
|
||||
* **[website] Refactor resource planning documentation**: Improved the resource planning guide with a clearer structure and more comprehensive coverage of planning considerations for Cozystack deployments ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#423).
|
||||
|
||||
* **[website] Add ServiceAccount API access documentation and update FAQ**: Added a new article documenting ServiceAccount API access token configuration and updated the FAQ to include related troubleshooting guidance ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#421).
|
||||
|
||||
* **[website] Update networking-mesh allowed-location-ips example**: Replaced provider-specific CLI usage with standard `kubectl` commands in the multi-location networking guide's `allowed-location-ips` example, making the documentation more universally applicable ([**@kvaps**](https://github.com/kvaps) in cozystack/website#425).
|
||||
|
||||
## Contributors
|
||||
|
||||
We'd like to thank all contributors who made this release possible:
|
||||
|
||||
* [**@IvanHunters**](https://github.com/IvanHunters)
|
||||
* [**@IvanStukov**](https://github.com/IvanStukov)
|
||||
* [**@kvaps**](https://github.com/kvaps)
|
||||
* [**@lexfrei**](https://github.com/lexfrei)
|
||||
* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil)
|
||||
* [**@nbykov0**](https://github.com/nbykov0)
|
||||
* [**@sircthulhu**](https://github.com/sircthulhu)
|
||||
|
||||
### New Contributors
|
||||
|
||||
We're excited to welcome our first-time contributors:
|
||||
|
||||
* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) - First contribution!
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0-beta.6...v1.0.0-rc.1
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.35@sha256:39f626c802dd84f95720ffb54fcd80dfb8a58ac280498870d0a1aa30d4252f94
|
||||
ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:19ee4c76f0b3b7b40b97995ca78988ad8c82f6e9c75288d8b7b4b88a64f75d50
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{{- $targetTenant := .Values._namespace.monitoring }}
|
||||
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
|
||||
{{- if .Values.addons.monitoringAgents.enabled }}
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
@@ -50,7 +49,7 @@ spec:
|
||||
cluster: {{ .Release.Name }}
|
||||
tenant: {{ .Release.Namespace }}
|
||||
remoteWrite:
|
||||
url: http://vminsert-shortterm.{{ $targetTenant }}.svc.{{ $clusterDomain }}:8480/insert/0/prometheus
|
||||
url: http://vminsert-shortterm.{{ $targetTenant }}.svc:8480/insert/0/prometheus
|
||||
fluent-bit:
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
@@ -73,7 +72,7 @@ spec:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match kube.*
|
||||
Host vlogs-generic.{{ $targetTenant }}.svc.{{ $clusterDomain }}
|
||||
Host vlogs-generic.{{ $targetTenant }}.svc
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=stream,kubernetes_pod_name,kubernetes_container_name,kubernetes_namespace_name&_msg_field=log&_time_field=date
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
cozystackOperator:
|
||||
# Deployment variant: talos, generic, hosted
|
||||
variant: talos
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.0.0-rc.1@sha256:5c0148116b2ab425106f6b86bbc1dfec593a83c993947c24eae92946d1c6116a
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.0.0-beta.6@sha256:c7490da9c1ccb51bff4dd5657ca6a33a29ac71ad9861dfa8c72fdfc8b5765b93
|
||||
platformSourceUrl: 'oci://ghcr.io/cozystack/cozystack/cozystack-packages'
|
||||
platformSourceRef: 'digest=sha256:b4ee831911b9c259a073f00390559f0bd5d8c78e22e48427a64ef05ed90ca008'
|
||||
platformSourceRef: 'digest=sha256:b29b87d1a2b80452ffd4db7516a102c30c55121552dcdb237055d4124d12c55d'
|
||||
# Generic variant configuration (only used when cozystackOperator.variant=generic)
|
||||
cozystack:
|
||||
# Kubernetes API server host (IP only, no protocol/port)
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
apiVersion: cozystack.io/v1alpha1
|
||||
kind: PackageSource
|
||||
metadata:
|
||||
name: cozystack.cozystack-scheduler
|
||||
spec:
|
||||
sourceRef:
|
||||
kind: OCIRepository
|
||||
name: cozystack-packages
|
||||
namespace: cozy-system
|
||||
path: /
|
||||
variants:
|
||||
- name: default
|
||||
components:
|
||||
- name: cozystack-scheduler
|
||||
path: system/cozystack-scheduler
|
||||
install:
|
||||
namespace: kube-system
|
||||
releaseName: cozystack-scheduler
|
||||
@@ -155,6 +155,5 @@
|
||||
{{include "cozystack.platform.package.default" (list "cozystack.bootbox" $) }}
|
||||
{{- end }}
|
||||
{{include "cozystack.platform.package.optional.default" (list "cozystack.hetzner-robotlb" $) }}
|
||||
{{include "cozystack.platform.package.optional.default" (list "cozystack.cozystack-scheduler" $) }}
|
||||
|
||||
{{- end }}
|
||||
|
||||
@@ -5,7 +5,7 @@ sourceRef:
|
||||
path: /
|
||||
migrations:
|
||||
enabled: false
|
||||
image: ghcr.io/cozystack/cozystack/platform-migrations:v1.0.0-rc.1@sha256:21a09c9f8dfd0a0c9b8c14c70029a39bfce021c66f1d4cacad9764c35dce6e8f
|
||||
image: ghcr.io/cozystack/cozystack/platform-migrations:v1.0.0-beta.6@sha256:37c78dafcedbdad94acd9912550db0b4875897150666b8a06edfa894de99064e
|
||||
targetVersion: 33
|
||||
# Bundle deployment configuration
|
||||
bundles:
|
||||
@@ -46,7 +46,7 @@ publishing:
|
||||
apiServerEndpoint: "" # example: "https://api.example.org"
|
||||
externalIPs: []
|
||||
certificates:
|
||||
solver: http01 # "http01" or "dns01"
|
||||
solver: http01 # "http01" or "dns01"
|
||||
issuerName: letsencrypt-prod
|
||||
# Authentication configuration
|
||||
authentication:
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
e2e:
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.0.0-rc.1@sha256:0eae9f519669667d60b160ebb93c127843c470ad9ca3447fceaa54604503a7ba
|
||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.0.0-beta.6@sha256:09af5901abcbed2b612d2d93c163e8ad3948bc55a1d8beae714b4fb2b8f7d91d
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/matchbox:v1.0.0-rc.1@sha256:3306de19f1ad49a02c735d16b82d7c2ec015c8e0563f120f216274e9a3804431
|
||||
ghcr.io/cozystack/cozystack/matchbox:v1.0.0-beta.6@sha256:212f624957447f5a932fd5d4564eb8c97694d336b7dc877a2833c1513c0d074d
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-rc.1@sha256:235b194a531b70e266a10ef78d2955d19f5b659513f23d8b3cfbbc0dff7fc1c0
|
||||
ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-beta.6@sha256:235b194a531b70e266a10ef78d2955d19f5b659513f23d8b3cfbbc0dff7fc1c0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
backupController:
|
||||
image: "ghcr.io/cozystack/cozystack/backup-controller:v1.0.0-rc.1@sha256:0bb4173bdcd3d917a7bd358ecc2c6a053a06ab0bd1fcdb89d1016a66173e6dfb"
|
||||
image: "ghcr.io/cozystack/cozystack/backup-controller:v1.0.0-beta.6@sha256:365214a74ffc34a9314a62a7d4b491590051fc5486f6bae9913c0c1289983d43"
|
||||
replicas: 2
|
||||
debug: false
|
||||
metrics:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
backupStrategyController:
|
||||
image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.0.0-rc.1@sha256:c2d975574ea9edcd785b533e01add37909959a64ef815529162dfe1f472ea702"
|
||||
image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.0.0-beta.6@sha256:aa04ee61dce11950162606fc8db2d5cbc6f5b32ba700f790b3f1eee10d65efb1"
|
||||
replicas: 2
|
||||
debug: false
|
||||
metrics:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
cozystackAPI:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v1.0.0-rc.1@sha256:9195ac6ef1d29aba3e1903f29a9aeeb72f5bf7ba3dbd7ebd866a06a4433e5915
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v1.0.0-beta.6@sha256:d89cf68fb622d0dbef7db98db09d352efc93c2cce448d11f2d73dcd363e911b7
|
||||
replicas: 2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cozystackController:
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.0.0-rc.1@sha256:0ac4b6d55daf79e2a7a045cd21b48ba598ac2628442fd9c4d0556cf9af6b83be
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.0.0-beta.6@sha256:d55a3c288934b1f69a00321bc8a94776915556b5f882fe6ac615e9de2701c61f
|
||||
debug: false
|
||||
disableTelemetry: false
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
apiVersion: v2
|
||||
name: cozy-cozystack-scheduler
|
||||
version: 0.1.0
|
||||
@@ -1,10 +0,0 @@
|
||||
export NAME=cozystack-scheduler
|
||||
export NAMESPACE=kube-system
|
||||
|
||||
include ../../../hack/package.mk
|
||||
|
||||
update:
|
||||
rm -rf crds templates values.yaml Chart.yaml
|
||||
tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/cozystack/cozystack-scheduler | awk -F'[/^]' 'END{print $$3}') && \
|
||||
curl -sSL https://github.com/cozystack/cozystack-scheduler/archive/refs/tags/$${tag}.tar.gz | \
|
||||
tar xzvf - --strip 2 cozystack-scheduler-$${tag#*v}/chart
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: cozystack-scheduler
|
||||
rules:
|
||||
- apiGroups: ["cozystack.io"]
|
||||
resources:
|
||||
- schedulingclasses
|
||||
verbs: ["get", "list", "watch"]
|
||||
@@ -1,38 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: cozystack-scheduler:kube-scheduler
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:kube-scheduler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cozystack-scheduler
|
||||
namespace: {{ .Release.Namespace }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: cozystack-scheduler:volume-scheduler
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:volume-scheduler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cozystack-scheduler
|
||||
namespace: {{ .Release.Namespace }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: cozystack-scheduler
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cozystack-scheduler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cozystack-scheduler
|
||||
namespace: {{ .Release.Namespace }}
|
||||
@@ -1,54 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cozystack-scheduler-config
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
scheduler-config.yaml: |
|
||||
apiVersion: kubescheduler.config.k8s.io/v1
|
||||
kind: KubeSchedulerConfiguration
|
||||
leaderElection:
|
||||
leaderElect: true
|
||||
resourceNamespace: {{ .Release.Namespace }}
|
||||
resourceName: cozystack-scheduler
|
||||
profiles:
|
||||
- schedulerName: cozystack-scheduler
|
||||
plugins:
|
||||
preFilter:
|
||||
disabled:
|
||||
- name: InterPodAffinity
|
||||
- name: NodeAffinity
|
||||
- name: PodTopologySpread
|
||||
enabled:
|
||||
- name: CozystackInterPodAffinity
|
||||
- name: CozystackNodeAffinity
|
||||
- name: CozystackPodTopologySpread
|
||||
- name: CozystackSchedulingClass
|
||||
filter:
|
||||
disabled:
|
||||
- name: InterPodAffinity
|
||||
- name: NodeAffinity
|
||||
- name: PodTopologySpread
|
||||
enabled:
|
||||
- name: CozystackInterPodAffinity
|
||||
- name: CozystackNodeAffinity
|
||||
- name: CozystackPodTopologySpread
|
||||
- name: CozystackSchedulingClass
|
||||
preScore:
|
||||
disabled:
|
||||
- name: InterPodAffinity
|
||||
- name: NodeAffinity
|
||||
- name: PodTopologySpread
|
||||
enabled:
|
||||
- name: CozystackInterPodAffinity
|
||||
- name: CozystackNodeAffinity
|
||||
- name: CozystackPodTopologySpread
|
||||
score:
|
||||
disabled:
|
||||
- name: InterPodAffinity
|
||||
- name: NodeAffinity
|
||||
- name: PodTopologySpread
|
||||
enabled:
|
||||
- name: CozystackInterPodAffinity
|
||||
- name: CozystackNodeAffinity
|
||||
- name: CozystackPodTopologySpread
|
||||
@@ -1,37 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cozystack-scheduler
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cozystack-scheduler
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cozystack-scheduler
|
||||
spec:
|
||||
serviceAccountName: cozystack-scheduler
|
||||
containers:
|
||||
- name: cozystack-scheduler
|
||||
image: {{ .Values.image }}
|
||||
command:
|
||||
- /cozystack-scheduler
|
||||
- --config=/etc/kubernetes/scheduler-config.yaml
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10259
|
||||
scheme: HTTPS
|
||||
initialDelaySeconds: 15
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/kubernetes/scheduler-config.yaml
|
||||
subPath: scheduler-config.yaml
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: cozystack-scheduler-config
|
||||
@@ -1,40 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: cozystack-scheduler:extension-apiserver-authentication-reader
|
||||
namespace: kube-system
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: extension-apiserver-authentication-reader
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cozystack-scheduler
|
||||
namespace: {{ .Release.Namespace }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: cozystack-scheduler:leader-election
|
||||
namespace: {{ .Release.Namespace }}
|
||||
rules:
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resources: ["leases"]
|
||||
verbs: ["create", "get", "list", "update", "watch"]
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resources: ["leasecandidates"]
|
||||
verbs: ["create", "get", "list", "update", "watch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: cozystack-scheduler:leader-election
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: cozystack-scheduler:leader-election
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cozystack-scheduler
|
||||
namespace: {{ .Release.Namespace }}
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: cozystack-scheduler
|
||||
namespace: {{ .Release.Namespace }}
|
||||
@@ -1,2 +0,0 @@
|
||||
image: ghcr.io/cozystack/cozystack/cozystack-scheduler:v0.1.0@sha256:5f7150c82177478467ff80628acb5a400291aff503364aa9e26fc346d79a73cf
|
||||
replicas: 1
|
||||
@@ -1,6 +1,6 @@
|
||||
{{- $brandingConfig := .Values._cluster.branding | default dict }}
|
||||
|
||||
{{- $tenantText := "v1.0.0-rc.1" }}
|
||||
{{- $tenantText := "v1.0.0-beta.6" }}
|
||||
{{- $footerText := "Cozystack" }}
|
||||
{{- $titleText := "Cozystack Dashboard" }}
|
||||
{{- $logoText := "" }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
openapiUI:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v1.0.0-rc.1@sha256:26e787b259ab8722d61f89e07eda200ef2180ed10b0df8596d75bba15526feb0
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui:v1.0.0-beta.6@sha256:c333637673a9e878f6c4ed0fc96db55967bbcf94b2434d075b0f0c6fcfcf9eff
|
||||
openapiUIK8sBff:
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.0.0-rc.1@sha256:0f508427bfa5a650eda6c5ef01ea32a586ac485a54902d7649ec49cc84f676f7
|
||||
image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.0.0-beta.6@sha256:1b3ea6d4c7dbbe6a8def3b2807fffdfab2ac4afc39d7a846e57dd491fa168f92
|
||||
tokenProxy:
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v1.0.0-rc.1@sha256:2e280991e07853ea48f97b0a42946afffa10d03d6a83d41099ed83e6ffc94fdc
|
||||
image: ghcr.io/cozystack/cozystack/token-proxy:v1.0.0-beta.6@sha256:2e280991e07853ea48f97b0a42946afffa10d03d6a83d41099ed83e6ffc94fdc
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/grafana-dashboards:v1.0.0-rc.1@sha256:7a3c9af59f8d74d5a23750bbc845c7de64610dbd4d4f84011e10be037b3ce2a0
|
||||
ghcr.io/cozystack/cozystack/grafana-dashboards:v1.0.0-beta.6@sha256:7a3c9af59f8d74d5a23750bbc845c7de64610dbd4d4f84011e10be037b3ce2a0
|
||||
|
||||
@@ -3,7 +3,7 @@ kamaji:
|
||||
deploy: false
|
||||
image:
|
||||
pullPolicy: IfNotPresent
|
||||
tag: v1.0.0-rc.1@sha256:0ca47c0d72a198f52f029bea30e89557680eac65c7914369b092d8ed9cc9997b
|
||||
tag: v1.0.0-beta.6@sha256:05f8e166dc94aadb74cd6448f6f96fbd2167057a559097516a41b8f53e434918
|
||||
repository: ghcr.io/cozystack/cozystack/kamaji
|
||||
resources:
|
||||
limits:
|
||||
@@ -13,4 +13,4 @@ kamaji:
|
||||
cpu: 100m
|
||||
memory: 100Mi
|
||||
extraArgs:
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v1.0.0-rc.1@sha256:0ca47c0d72a198f52f029bea30e89557680eac65c7914369b092d8ed9cc9997b
|
||||
- --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v1.0.0-beta.6@sha256:05f8e166dc94aadb74cd6448f6f96fbd2167057a559097516a41b8f53e434918
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v1.0.0-rc.1@sha256:6be9aa4b2dda15bf7300bd961cbc71c8bbf9ce97bc3cf613ef5a012d329b4e70
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v1.0.0-beta.6@sha256:8e964605efe54e73a94c84abec7dbb5a011c02ccece282bef8ae7b70fce3d217
|
||||
ovnCentralName: ovn-central
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
portSecurity: true
|
||||
routes: ""
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v1.0.0-rc.1@sha256:e18f9fd679e38f65362a8d0042f25468272f6d081136ad47027168d8e7e07a4a
|
||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v1.0.0-beta.6@sha256:e18f9fd679e38f65362a8d0042f25468272f6d081136ad47027168d8e7e07a4a
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
lineageControllerWebhook:
|
||||
image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.0.0-rc.1@sha256:473ed28fcd7ddc35319a0fd33dd0fff3e56491b572677545a6e317b53578c53d
|
||||
image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.0.0-beta.6@sha256:cf577e56ebc2b94205741d9c5b08f2983cec0811f0c2890edca8fdca22624de1
|
||||
debug: false
|
||||
localK8sAPIEndpoint:
|
||||
enabled: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
piraeusServer:
|
||||
image:
|
||||
repository: ghcr.io/cozystack/cozystack/piraeus-server
|
||||
tag: 1.32.3@sha256:59806529a090cb42e2fa2696e09814282b80e76a299b5fe9feec46772edd6876
|
||||
tag: 1.32.3@sha256:66eadfc98cd809d2b3c4e6fd631bcd0c4b4cd72a7fb819ac4a0cab7904280546
|
||||
# Talos-specific workarounds (disable for generic Linux like Ubuntu/Debian)
|
||||
talos:
|
||||
enabled: true
|
||||
|
||||
@@ -280,8 +280,8 @@ vmagent:
|
||||
cluster: cozystack
|
||||
remoteWrite:
|
||||
urls:
|
||||
- http://vminsert-shortterm.{{ .Values.global.target }}.svc:8480/insert/0/prometheus
|
||||
- http://vminsert-longterm.{{ .Values.global.target }}.svc:8480/insert/0/prometheus
|
||||
- http://vminsert-shortterm.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}:8480/insert/0/prometheus
|
||||
- http://vminsert-longterm.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}:8480/insert/0/prometheus
|
||||
extraArgs: {}
|
||||
|
||||
fluent-bit:
|
||||
@@ -344,7 +344,7 @@ fluent-bit:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match kube.*
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=log_source,stream,kubernetes_pod_name,kubernetes_container_name,kubernetes_namespace_name&_msg_field=log&_time_field=date
|
||||
@@ -355,7 +355,7 @@ fluent-bit:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match events.*
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=log_source,reason,meatdata_namespace,metadata_name&_msg_field=message&_time_field=date
|
||||
@@ -366,7 +366,7 @@ fluent-bit:
|
||||
[OUTPUT]
|
||||
Name http
|
||||
Match audit.*
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc
|
||||
Host vlogs-generic.{{ .Values.global.target }}.svc.{{ (index .Values._cluster "cluster-domain") | default "cluster.local" }}
|
||||
port 9428
|
||||
compress gzip
|
||||
uri /insert/jsonline?_stream_fields=log_source,stage,user_username,verb,requestUri&_msg_field=requestURI&_time_field=date
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
objectstorage:
|
||||
controller:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v1.0.0-rc.1@sha256:b4c972769afda76c48b58e7acf0ac66a0abf16a622f245c60338f432872f640a"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v1.0.0-beta.6@sha256:b4c972769afda76c48b58e7acf0ac66a0abf16a622f245c60338f432872f640a"
|
||||
|
||||
@@ -177,7 +177,7 @@ seaweedfs:
|
||||
bucketClassName: "seaweedfs"
|
||||
region: ""
|
||||
sidecar:
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-rc.1@sha256:235b194a531b70e266a10ef78d2955d19f5b659513f23d8b3cfbbc0dff7fc1c0"
|
||||
image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-beta.6@sha256:235b194a531b70e266a10ef78d2955d19f5b659513f23d8b3cfbbc0dff7fc1c0"
|
||||
certificates:
|
||||
commonName: "SeaweedFS CA"
|
||||
ipAddresses: []
|
||||
|
||||
Reference in New Issue
Block a user