remove unused file
Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
parent
8f9bcbd1ea
commit
9cad1ab490
|
|
@ -1,238 +0,0 @@
|
|||
# Custom Resource Tracking
|
||||
|
||||
This document describes how to configure custom resource tracking in the kubedog tracker.
|
||||
|
||||
## Overview
|
||||
|
||||
The kubedog tracker now supports flexible configuration for resource tracking through the `TrackOptions` struct. You can:
|
||||
|
||||
- **Track specific kinds**: Only track resources of specified types
|
||||
- **Skip specific kinds**: Exclude certain resource types from tracking
|
||||
- **Define custom trackable kinds**: Add new resource types that should be actively tracked
|
||||
- **Define custom static kinds**: Add new resource types that don't need active tracking
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### TrackKinds
|
||||
|
||||
When set, only resources in this list will be tracked. All other resources are ignored.
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
opts := NewTrackOptions().WithTrackKinds([]string{"Deployment", "StatefulSet"})
|
||||
```
|
||||
|
||||
This configuration will:
|
||||
- Track only `Deployment` and `StatefulSet` resources
|
||||
- Ignore all other resource types (Service, ConfigMap, etc.)
|
||||
|
||||
### SkipKinds
|
||||
|
||||
Resources in this list will be skipped, even if they would normally be tracked.
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
opts := NewTrackOptions().WithSkipKinds([]string{"ConfigMap", "Secret"})
|
||||
```
|
||||
|
||||
This configuration will:
|
||||
- Track all normally trackable resources (Deployment, StatefulSet, etc.)
|
||||
- Skip `ConfigMap` and `Secret` resources
|
||||
|
||||
### CustomTrackableKinds
|
||||
|
||||
Define additional resource types that should be actively tracked. When configured, only these custom types and resources in `TrackKinds` (if set) will be considered trackable.
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
opts := NewTrackOptions().WithCustomTrackableKinds([]string{"CronJob", "ReplicationController"})
|
||||
```
|
||||
|
||||
This configuration will:
|
||||
- Treat `CronJob` and `ReplicationController` as trackable resources
|
||||
- Ignore default trackable kinds (Deployment, StatefulSet, etc.) unless also in `TrackKinds`
|
||||
|
||||
### CustomStaticKinds
|
||||
|
||||
Define additional resource types that are considered static and don't need active tracking.
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
opts := NewTrackOptions().WithCustomStaticKinds([]string{"NetworkPolicy", "PodDisruptionBudget"})
|
||||
```
|
||||
|
||||
This configuration will:
|
||||
- Treat `NetworkPolicy` and `PodDisruptionBudget` as static resources
|
||||
- Ignore default static kinds unless not in this list
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: Track Only Deployments and StatefulSets
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/helmfile/helmfile/pkg/kubedog"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Configure tracker to only track Deployments and StatefulSets
|
||||
opts := kubedog.NewTrackOptions().
|
||||
WithTrackKinds([]string{"Deployment", "StatefulSet"}).
|
||||
WithTimeout(600)
|
||||
|
||||
config := &kubedog.TrackerConfig{
|
||||
Logger: zap.NewExample().Sugar(),
|
||||
Namespace: "default",
|
||||
KubeContext: "",
|
||||
Kubeconfig: "",
|
||||
TrackOptions: opts,
|
||||
}
|
||||
|
||||
tracker, err := kubedog.NewTracker(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
manifest := []byte(`
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: my-deployment
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: myapp
|
||||
ports:
|
||||
- port: 80
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: my-statefulset
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
`)
|
||||
|
||||
// This will track Deployment and StatefulSet, but skip Service
|
||||
err = tracker.TrackReleaseWithManifest(nil, "my-release", "default", manifest)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
tracker.Close()
|
||||
}
|
||||
```
|
||||
|
||||
### Example 2: Skip ConfigMaps and Secrets
|
||||
|
||||
```go
|
||||
opts := kubedog.NewTrackOptions().
|
||||
WithSkipKinds([]string{"ConfigMap", "Secret"})
|
||||
|
||||
// This will track all normally trackable resources (Deployment, StatefulSet, etc.)
|
||||
// but skip ConfigMap and Secret resources
|
||||
```
|
||||
|
||||
### Example 3: Add Custom Trackable Kind (CronJob)
|
||||
|
||||
```go
|
||||
opts := kubedog.NewTrackOptions().
|
||||
WithCustomTrackableKinds([]string{"CronJob"})
|
||||
|
||||
// This will treat CronJob as a trackable resource and wait for it
|
||||
// Default trackable kinds (Deployment, StatefulSet) will not be tracked
|
||||
```
|
||||
|
||||
### Example 4: Combined Configuration
|
||||
|
||||
```go
|
||||
opts := kubedog.NewTrackOptions().
|
||||
WithTrackKinds([]string{"Deployment", "CronJob"}).
|
||||
WithSkipKinds([]string{"ConfigMap"})
|
||||
|
||||
// This configuration:
|
||||
// 1. Only tracks Deployment and CronJob resources
|
||||
// 2. Skips ConfigMap even if it appears in the manifest
|
||||
// 3. Ignores all other resource types
|
||||
```
|
||||
|
||||
## Priority and Behavior
|
||||
|
||||
The tracker evaluates configuration in the following order:
|
||||
|
||||
1. **SkipKinds**: If a resource kind is in SkipKinds, it's immediately skipped
|
||||
2. **TrackKinds**: If TrackKinds is set, only resources in this list are considered
|
||||
3. **CustomTrackableKinds / CustomStaticKinds**:
|
||||
- If CustomTrackableKinds is set, only these kinds are considered trackable
|
||||
- If CustomStaticKinds is set, only these kinds are considered static
|
||||
- Otherwise, default trackable/static lists are used
|
||||
|
||||
## Resource Classification
|
||||
|
||||
### Default Trackable Kinds
|
||||
|
||||
These resources are actively tracked by default:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
- DaemonSet
|
||||
- Job
|
||||
- Pod
|
||||
- ReplicaSet
|
||||
|
||||
### Default Static Kinds
|
||||
|
||||
These resources don't need active tracking by default:
|
||||
- Service
|
||||
- ConfigMap
|
||||
- Secret
|
||||
- PersistentVolume
|
||||
- PersistentVolumeClaim
|
||||
- StorageClass
|
||||
- Namespace
|
||||
- ResourceQuota
|
||||
- LimitRange
|
||||
- PriorityClass
|
||||
- ServiceAccount
|
||||
- Role
|
||||
- RoleBinding
|
||||
- ClusterRole
|
||||
- ClusterRoleBinding
|
||||
- NetworkPolicy
|
||||
- Ingress
|
||||
- CustomResourceDefinition
|
||||
|
||||
## Integration with Helmfile
|
||||
|
||||
When using kubedog tracker with Helmfile, you can configure tracking options in your helmfile.yaml:
|
||||
|
||||
```yaml
|
||||
releases:
|
||||
- name: my-app
|
||||
namespace: default
|
||||
chart: ./charts/my-app
|
||||
track:
|
||||
timeout: 600
|
||||
trackKinds:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
skipKinds:
|
||||
- ConfigMap
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [Resource Detection Guide](./RESOURCE_DETECTION.md)
|
||||
- [Helmfile README](../README.md)
|
||||
|
|
@ -1,302 +0,0 @@
|
|||
# Implementation Summary: Custom Resource Tracking
|
||||
|
||||
## Overview
|
||||
|
||||
Added custom resource tracking configuration to the kubedog tracker, allowing users to flexibly control which resources are tracked and how they are classified.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. TrackOptions Enhancements (`pkg/kubedog/options.go`)
|
||||
|
||||
Added new configuration fields to `TrackOptions` struct:
|
||||
|
||||
```go
|
||||
type TrackOptions struct {
|
||||
Timeout int
|
||||
Logs bool
|
||||
LogsSince int
|
||||
Namespace string
|
||||
KubeContext string
|
||||
Kubeconfig string
|
||||
// NEW FIELDS
|
||||
TrackKinds []string // Only track resources of these kinds
|
||||
SkipKinds []string // Skip resources of these kinds
|
||||
CustomTrackableKinds []string // Custom kinds that should be actively tracked
|
||||
CustomStaticKinds []string // Custom kinds that don't need tracking
|
||||
}
|
||||
```
|
||||
|
||||
Added builder methods:
|
||||
|
||||
```go
|
||||
func (o *TrackOptions) WithTrackKinds(kinds []string) *TrackOptions
|
||||
func (o *TrackOptions) WithSkipKinds(kinds []string) *TrackOptions
|
||||
func (o *TrackOptions) WithCustomTrackableKinds(kinds []string) *TrackOptions
|
||||
func (o *TrackOptions) WithCustomStaticKinds(kinds []string) *TrackOptions
|
||||
```
|
||||
|
||||
### 2. TrackConfig Structure (`pkg/cluster/release.go`)
|
||||
|
||||
Added `TrackConfig` struct to pass tracking configuration:
|
||||
|
||||
```go
|
||||
type TrackConfig struct {
|
||||
TrackKinds []string
|
||||
SkipKinds []string
|
||||
CustomTrackableKinds []string
|
||||
CustomStaticKinds []string
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Enhanced Resource Detection (`pkg/cluster/release.go`)
|
||||
|
||||
Added new functions for resource filtering and classification:
|
||||
|
||||
```go
|
||||
// Get resources with custom tracking configuration
|
||||
func GetReleaseResourcesFromManifestWithConfig(
|
||||
manifest []byte,
|
||||
releaseName, releaseNamespace string,
|
||||
config *TrackConfig,
|
||||
) (*ReleaseResources, error)
|
||||
|
||||
// Filter resources based on TrackKinds and SkipKinds
|
||||
func filterResourcesByConfig(
|
||||
resources []Resource,
|
||||
config *TrackConfig,
|
||||
logger *zap.SugaredLogger,
|
||||
) []Resource
|
||||
|
||||
// Check if resource is trackable with custom config
|
||||
func IsTrackableKindWithConfig(kind string, config *TrackConfig) bool
|
||||
|
||||
// Check if resource is static with custom config
|
||||
func IsStaticKindWithConfig(kind string, config *TrackConfig) bool
|
||||
```
|
||||
|
||||
### 4. Enhanced Tracker (`pkg/kubedog/tracker.go`)
|
||||
|
||||
Updated `TrackReleaseWithManifest` to use custom configuration:
|
||||
|
||||
```go
|
||||
func (t *Tracker) TrackReleaseWithManifest(
|
||||
ctx interface{},
|
||||
releaseName, releaseNamespace string,
|
||||
manifest []byte,
|
||||
) error {
|
||||
// Create TrackConfig from TrackOptions
|
||||
trackConfig := &cluster.TrackConfig{
|
||||
TrackKinds: t.options.TrackKinds,
|
||||
SkipKinds: t.options.SkipKinds,
|
||||
CustomTrackableKinds: t.options.CustomTrackableKinds,
|
||||
CustomStaticKinds: t.options.CustomStaticKinds,
|
||||
}
|
||||
|
||||
// Use config when getting resources
|
||||
releaseResources, err := cluster.GetReleaseResourcesFromManifestWithLogger(
|
||||
t.logger, manifest, releaseName, releaseNamespace, trackConfig,
|
||||
)
|
||||
|
||||
// Pass config when tracking resources
|
||||
return t.trackResources(ctx, releaseResources, trackConfig)
|
||||
}
|
||||
```
|
||||
|
||||
Added support for custom resources:
|
||||
|
||||
```go
|
||||
func (t *Tracker) trackCustomResource(ctx context.Context, res cluster.Resource) error {
|
||||
t.logger.Infof("Waiting for custom resource %s/%s to become ready", res.Namespace, res.Name)
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Behavior
|
||||
|
||||
### Priority Order
|
||||
|
||||
1. **SkipKinds**: Applied first - if a resource kind is in SkipKinds, it's skipped
|
||||
2. **TrackKinds**: If set, only resources in this list are considered
|
||||
3. **CustomTrackableKinds**: If set, only these kinds are considered trackable
|
||||
4. **CustomStaticKinds**: If set, only these kinds are considered static
|
||||
5. **Default Lists**: Fall back to default trackable/static kinds if no custom config
|
||||
|
||||
### Example Configurations
|
||||
|
||||
#### Only Track Deployments
|
||||
```go
|
||||
opts := NewTrackOptions().
|
||||
WithTrackKinds([]string{"Deployment"})
|
||||
```
|
||||
|
||||
#### Skip ConfigMaps
|
||||
```go
|
||||
opts := NewTrackOptions().
|
||||
WithSkipKinds([]string{"ConfigMap"})
|
||||
```
|
||||
|
||||
#### Add Custom Trackable Kind
|
||||
```go
|
||||
opts := NewTrackOptions().
|
||||
WithCustomTrackableKinds([]string{"CronJob"})
|
||||
```
|
||||
|
||||
#### Combined Configuration
|
||||
```go
|
||||
opts := NewTrackOptions().
|
||||
WithTrackKinds([]string{"Deployment", "StatefulSet"}).
|
||||
WithSkipKinds([]string{"ConfigMap"})
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### New Test Cases
|
||||
|
||||
#### Cluster Package Tests
|
||||
- `TestTrackConfig_TrackKinds` - Test filtering by TrackKinds
|
||||
- `TestTrackConfig_SkipKinds` - Test skipping by SkipKinds
|
||||
- `TestTrackConfig_CustomTrackableKinds` - Test custom trackable kinds
|
||||
- `TestTrackConfig_CustomStaticKinds` - Test custom static kinds
|
||||
- `TestTrackConfig_Combined` - Test combined configuration
|
||||
- `TestTrackConfig_Nil` - Test behavior with nil config
|
||||
|
||||
#### Kubedog Package Tests
|
||||
- `TestTrackReleaseWithManifest_TrackKinds` - Test tracker with TrackKinds
|
||||
- `TestTrackReleaseWithManifest_SkipKinds` - Test tracker with SkipKinds
|
||||
- `TestTrackReleaseWithManifest_CustomTrackableKinds` - Test tracker with custom kinds
|
||||
|
||||
### Test Results
|
||||
|
||||
```bash
|
||||
$ go test ./pkg/cluster/... -v
|
||||
PASS: TestGetReleaseResourcesFromManifest
|
||||
PASS: TestGetReleaseResourcesFromManifestWithLogger
|
||||
PASS: TestIsTrackableKind
|
||||
PASS: TestIsStaticKind
|
||||
PASS: TestGetHelmReleaseLabels
|
||||
PASS: TestGetHelmReleaseAnnotations
|
||||
PASS: TestParseManifest
|
||||
PASS: TestParseManifest_Empty
|
||||
PASS: TestParseManifest_Nil
|
||||
PASS: TestResource_ManifestContent
|
||||
PASS: TestTrackConfig_TrackKinds
|
||||
PASS: TestTrackConfig_SkipKinds
|
||||
PASS: TestTrackConfig_CustomTrackableKinds
|
||||
PASS: TestTrackConfig_CustomStaticKinds
|
||||
PASS: TestTrackConfig_Combined
|
||||
PASS: TestTrackConfig_Nil
|
||||
PASS: TestDetectServerVersion_Integration
|
||||
PASS: TestDetectServerVersion_InvalidConfig
|
||||
ok github.com/helmfile/helmfile/pkg/cluster
|
||||
|
||||
$ go test ./pkg/kubedog/... -v
|
||||
PASS: TestNewTracker
|
||||
PASS: TestTracker_Close
|
||||
PASS: TestTrackRelease_WithNoNamespace
|
||||
PASS: TestTrackOptions
|
||||
PASS: TestTrackMode
|
||||
PASS: TestTrackReleaseWithManifest
|
||||
PASS: TestTrackReleaseWithManifest_Empty
|
||||
PASS: TestTrackReleaseWithManifest_InvalidYAML
|
||||
PASS: TestTrackReleaseWithManifest_TrackKinds
|
||||
PASS: TestTrackReleaseWithManifest_SkipKinds
|
||||
PASS: TestTrackReleaseWithManifest_CustomTrackableKinds
|
||||
ok github.com/helmfile/helmfile/pkg/kubedog
|
||||
|
||||
$ make check
|
||||
(All checks pass)
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
### New Documentation Files
|
||||
|
||||
1. **docs/CUSTOM_TRACKING.md** - Comprehensive guide on custom tracking configuration
|
||||
- Overview of all configuration options
|
||||
- Usage examples for each option
|
||||
- Priority and behavior explanation
|
||||
- Default resource classifications
|
||||
- Integration examples
|
||||
|
||||
2. **examples/custom_tracking/main.go** - Working example program
|
||||
- Example 1: Default tracking (all resources)
|
||||
- Example 2: Track only Deployments and StatefulSets
|
||||
- Example 3: Skip ConfigMaps
|
||||
- Example 4: Custom trackable kinds (CronJob)
|
||||
- Example 5: Custom static kinds
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/helmfile/helmfile/pkg/kubedog"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Configure tracker to track only Deployments and StatefulSets
|
||||
opts := kubedog.NewTrackOptions().
|
||||
WithTrackKinds([]string{"Deployment", "StatefulSet"}).
|
||||
WithTimeout(600)
|
||||
|
||||
config := &kubedog.TrackerConfig{
|
||||
Logger: zap.NewExample().Sugar(),
|
||||
Namespace: "default",
|
||||
TrackOptions: opts,
|
||||
}
|
||||
|
||||
tracker, err := kubedog.NewTracker(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
manifest := []byte(`... helm template output ...`)
|
||||
|
||||
err = tracker.TrackReleaseWithManifest(nil, "my-release", "default", manifest)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
tracker.Close()
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
```go
|
||||
// Track only specific kinds, skip certain kinds, and add custom trackable kinds
|
||||
opts := kubedog.NewTrackOptions().
|
||||
WithTrackKinds([]string{"Deployment", "StatefulSet", "CronJob"}).
|
||||
WithSkipKinds([]string{"ConfigMap", "Secret"}).
|
||||
WithCustomTrackableKinds([]string{"CronJob"}).
|
||||
WithTimeout(300)
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Flexibility**: Users can control exactly which resources are tracked
|
||||
2. **Performance**: Skip tracking unnecessary resources to save time
|
||||
3. **Customization**: Support for custom resource types (CRDs)
|
||||
4. **Fine-grained Control**: Combine multiple options for precise control
|
||||
5. **Backward Compatible**: Default behavior unchanged when no custom config is set
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
All changes are backward compatible:
|
||||
|
||||
- New fields in `TrackOptions` have default nil values
|
||||
- When all new fields are nil, behavior is identical to previous version
|
||||
- Existing functions `IsTrackableKind()` and `IsStaticKind()` still work
|
||||
- New functions `IsTrackableKindWithConfig()` and `IsStaticKindWithConfig()` accept nil config
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential future improvements:
|
||||
|
||||
1. **Pattern Matching**: Support wildcards and regex in TrackKinds/SkipKinds
|
||||
2. **Label-based Filtering**: Track resources based on labels/annotations
|
||||
3. **Resource Limits**: Limit number of resources tracked concurrently
|
||||
4. **Custom Tracking Logic**: Allow users to provide custom tracking functions
|
||||
5. **Configuration File**: Support loading tracking config from YAML/JSON files
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
# Resource Detection Based on Helm Template
|
||||
|
||||
This document describes the new resource detection feature based on Helm template manifest.
|
||||
|
||||
## Overview
|
||||
|
||||
The kubedog tracker now supports detecting resources by parsing Helm template output instead of querying the Kubernetes API. This approach has several advantages:
|
||||
|
||||
- No need to connect to a Kubernetes cluster
|
||||
- Faster execution
|
||||
- Works in dry-run and template modes
|
||||
- Simpler and more reliable
|
||||
|
||||
## Usage
|
||||
|
||||
### Track Release from Manifest
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/helmfile/helmfile/pkg/kubedog"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger := zap.NewExample().Sugar()
|
||||
|
||||
config := &kubedog.TrackerConfig{
|
||||
Logger: logger,
|
||||
Namespace: "default",
|
||||
KubeContext: "",
|
||||
Kubeconfig: "",
|
||||
TrackOptions: kubedog.NewTrackOptions(),
|
||||
}
|
||||
|
||||
tracker, err := kubedog.NewTracker(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
manifest := []byte(`
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: myapp
|
||||
ports:
|
||||
- port: 80
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: my-deployment
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: nginx:latest
|
||||
`)
|
||||
|
||||
err = tracker.TrackReleaseWithManifest(nil, "my-release", "default", manifest)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to track release: %v", err)
|
||||
}
|
||||
|
||||
tracker.Close()
|
||||
}
|
||||
```
|
||||
|
||||
### Parse Manifest Directly
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/helmfile/helmfile/pkg/cluster"
|
||||
)
|
||||
|
||||
func parseHelmOutput(manifest []byte) {
|
||||
releaseResources, err := cluster.GetReleaseResourcesFromManifest(
|
||||
manifest,
|
||||
"my-release",
|
||||
"default",
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Found %d resources:\n", len(releaseResources.Resources))
|
||||
for _, res := range releaseResources.Resources {
|
||||
fmt.Printf(" - %s/%s in namespace %s\n", res.Kind, res.Name, res.Namespace)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Resource Classification
|
||||
|
||||
### Trackable Resources
|
||||
|
||||
Resources that need active tracking (wait for ready/completed):
|
||||
|
||||
- **Deployment** - Wait for all replicas to be ready
|
||||
- **StatefulSet** - Wait for all replicas to be ready
|
||||
- **DaemonSet** - Wait for desired number of scheduled nodes
|
||||
- **Job** - Wait for job completion
|
||||
- **Pod** - Wait for pod to be ready
|
||||
- **ReplicaSet** - Wait for all replicas to be ready
|
||||
|
||||
### Static Resources
|
||||
|
||||
Resources that don't need active tracking (instantaneous creation):
|
||||
|
||||
- Service
|
||||
- ConfigMap
|
||||
- Secret
|
||||
- PersistentVolume
|
||||
- PersistentVolumeClaim
|
||||
- StorageClass
|
||||
- Namespace
|
||||
- ResourceQuota
|
||||
- LimitRange
|
||||
- PriorityClass
|
||||
- ServiceAccount
|
||||
- Role
|
||||
- RoleBinding
|
||||
- ClusterRole
|
||||
- ClusterRoleBinding
|
||||
- NetworkPolicy
|
||||
- Ingress
|
||||
- CustomResourceDefinition
|
||||
|
||||
## Helper Functions
|
||||
|
||||
### Check if a resource kind is trackable
|
||||
|
||||
```go
|
||||
isTrackable := cluster.IsTrackableKind("Deployment")
|
||||
```
|
||||
|
||||
### Check if a resource kind is static
|
||||
|
||||
```go
|
||||
isStatic := cluster.IsStaticKind("ConfigMap")
|
||||
```
|
||||
|
||||
### Get Helm release labels
|
||||
|
||||
```go
|
||||
labels := cluster.GetHelmReleaseLabels("my-release", "default")
|
||||
// Returns:
|
||||
// map[string]string{
|
||||
// "meta.helm.sh/release-name": "my-release",
|
||||
// "meta.helm.sh/release-namespace": "default",
|
||||
// }
|
||||
```
|
||||
|
||||
### Get Helm release annotations
|
||||
|
||||
```go
|
||||
annotations := cluster.GetHelmReleaseAnnotations("my-release")
|
||||
// Returns:
|
||||
// map[string]string{
|
||||
// "meta.helm.sh/release-name": "my-release",
|
||||
// }
|
||||
```
|
||||
|
||||
## Integration with Helmfile
|
||||
|
||||
The tracker can be integrated with Helmfile to track releases after installation:
|
||||
|
||||
```go
|
||||
func (st *HelmState) trackRelease(release *ReleaseSpec) error {
|
||||
if st.Tracker == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
manifest, err := st.getManifest(release)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return st.Tracker.TrackReleaseWithManifest(
|
||||
context.Background(),
|
||||
release.Name,
|
||||
release.Namespace,
|
||||
manifest,
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Advantages Over API-Based Detection
|
||||
|
||||
1. **No Cluster Access**: Works even without connecting to the cluster
|
||||
2. **Faster**: No need to query multiple resource types via API
|
||||
3. **Deterministic**: Always returns the same resources for the same manifest
|
||||
4. **Offline Friendly**: Can be used for planning and validation
|
||||
5. **Simpler**: Less complex error handling and retry logic
|
||||
|
||||
## Testing
|
||||
|
||||
The feature includes comprehensive tests:
|
||||
|
||||
```bash
|
||||
# Run cluster package tests
|
||||
go test ./pkg/cluster/... -v
|
||||
|
||||
# Run kubedog package tests
|
||||
go test ./pkg/kubedog/... -v
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
- Uses `k8s.io/apimachinery/pkg/util/yaml` for parsing
|
||||
- Handles multi-document YAML files (separated by `---`)
|
||||
- Extracts resource kind, name, namespace, and manifest
|
||||
- Skips resources without kind or name
|
||||
- Returns empty resource list for empty manifests
|
||||
2
go.mod
2
go.mod
|
|
@ -107,7 +107,7 @@ require (
|
|||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/yaml v1.6.0
|
||||
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
|||
|
|
@ -1,275 +0,0 @@
|
|||
package cluster
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
type Resource struct {
|
||||
Kind string
|
||||
Name string
|
||||
Namespace string
|
||||
Manifest string
|
||||
}
|
||||
|
||||
type ReleaseResources struct {
|
||||
ReleaseName string
|
||||
Namespace string
|
||||
Resources []Resource
|
||||
}
|
||||
|
||||
type TrackConfig struct {
|
||||
TrackKinds []string
|
||||
SkipKinds []string
|
||||
CustomTrackableKinds []string
|
||||
CustomStaticKinds []string
|
||||
}
|
||||
|
||||
func GetReleaseResourcesFromManifest(manifest []byte, releaseName, releaseNamespace string) (*ReleaseResources, error) {
|
||||
return GetReleaseResourcesFromManifestWithLogger(nil, manifest, releaseName, releaseNamespace, nil)
|
||||
}
|
||||
|
||||
func GetReleaseResourcesFromManifestWithConfig(manifest []byte, releaseName, releaseNamespace string, config *TrackConfig) (*ReleaseResources, error) {
|
||||
return GetReleaseResourcesFromManifestWithLogger(nil, manifest, releaseName, releaseNamespace, config)
|
||||
}
|
||||
|
||||
func GetReleaseResourcesFromManifestWithLogger(logger *zap.SugaredLogger, manifest []byte, releaseName, releaseNamespace string, config *TrackConfig) (*ReleaseResources, error) {
|
||||
resources, err := parseManifest(manifest, logger)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse manifest: %w", err)
|
||||
}
|
||||
|
||||
if len(resources) == 0 {
|
||||
if logger != nil {
|
||||
logger.Debugf("No resources found in manifest for release %s", releaseName)
|
||||
}
|
||||
return &ReleaseResources{
|
||||
ReleaseName: releaseName,
|
||||
Namespace: releaseNamespace,
|
||||
Resources: resources,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
filteredResources := filterResourcesByConfig(resources, config, logger)
|
||||
if logger != nil {
|
||||
logger.Infof("Found %d resources in manifest for release %s (filtered from %d total)", len(filteredResources), releaseName, len(resources))
|
||||
for _, res := range filteredResources {
|
||||
logger.Debugf(" - %s/%s in namespace %s", res.Kind, res.Name, res.Namespace)
|
||||
}
|
||||
}
|
||||
return &ReleaseResources{
|
||||
ReleaseName: releaseName,
|
||||
Namespace: releaseNamespace,
|
||||
Resources: filteredResources,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if logger != nil {
|
||||
logger.Infof("Found %d resources in manifest for release %s", len(resources), releaseName)
|
||||
for _, res := range resources {
|
||||
logger.Debugf(" - %s/%s in namespace %s", res.Kind, res.Name, res.Namespace)
|
||||
}
|
||||
}
|
||||
|
||||
return &ReleaseResources{
|
||||
ReleaseName: releaseName,
|
||||
Namespace: releaseNamespace,
|
||||
Resources: resources,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func filterResourcesByConfig(resources []Resource, config *TrackConfig, logger *zap.SugaredLogger) []Resource {
|
||||
var filtered []Resource
|
||||
|
||||
for _, res := range resources {
|
||||
if shouldSkipResource(res.Kind, config, logger) {
|
||||
if logger != nil {
|
||||
logger.Debugf("Skipping resource %s/%s (kind: %s) based on configuration", res.Kind, res.Name, res.Kind)
|
||||
}
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, res)
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func shouldSkipResource(kind string, config *TrackConfig, logger *zap.SugaredLogger) bool {
|
||||
if len(config.TrackKinds) > 0 {
|
||||
shouldTrack := false
|
||||
for _, trackKind := range config.TrackKinds {
|
||||
if kind == trackKind {
|
||||
shouldTrack = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !shouldTrack {
|
||||
if logger != nil {
|
||||
logger.Debugf("Resource kind %s is not in TrackKinds list, skipping", kind)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.SkipKinds) > 0 {
|
||||
for _, skipKind := range config.SkipKinds {
|
||||
if kind == skipKind {
|
||||
if logger != nil {
|
||||
logger.Debugf("Resource kind %s is in SkipKinds list, skipping", kind)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func parseManifest(manifest []byte, logger *zap.SugaredLogger) ([]Resource, error) {
|
||||
var resources []Resource
|
||||
|
||||
decoder := k8syaml.NewYAMLOrJSONDecoder(bytes.NewReader(manifest), 4096)
|
||||
|
||||
for {
|
||||
var obj unstructured.Unstructured
|
||||
err := decoder.Decode(&obj)
|
||||
if err != nil {
|
||||
if err.Error() == "EOF" {
|
||||
break
|
||||
}
|
||||
return nil, fmt.Errorf("failed to decode manifest: %w", err)
|
||||
}
|
||||
|
||||
if len(obj.Object) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
kind := obj.GetKind()
|
||||
if kind == "" {
|
||||
if logger != nil {
|
||||
logger.Debugf("Skipping resource without kind")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
name := obj.GetName()
|
||||
if name == "" {
|
||||
if logger != nil {
|
||||
logger.Debugf("Skipping %s resource without name", kind)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
namespace := obj.GetNamespace()
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
|
||||
manifestBytes, err := yaml.Marshal(obj.Object)
|
||||
if err != nil {
|
||||
if logger != nil {
|
||||
logger.Debugf("Failed to marshal %s/%s: %v", kind, name, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
res := Resource{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
Manifest: string(manifestBytes),
|
||||
}
|
||||
resources = append(resources, res)
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func IsTrackableKind(kind string) bool {
|
||||
trackableKinds := map[string]bool{
|
||||
"Deployment": true,
|
||||
"StatefulSet": true,
|
||||
"DaemonSet": true,
|
||||
"Job": true,
|
||||
"Pod": true,
|
||||
"ReplicaSet": true,
|
||||
}
|
||||
return trackableKinds[kind]
|
||||
}
|
||||
|
||||
func IsTrackableKindWithConfig(kind string, config *TrackConfig) bool {
|
||||
if config == nil {
|
||||
return IsTrackableKind(kind)
|
||||
}
|
||||
|
||||
if len(config.CustomTrackableKinds) > 0 {
|
||||
for _, customKind := range config.CustomTrackableKinds {
|
||||
if kind == customKind {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return IsTrackableKind(kind)
|
||||
}
|
||||
|
||||
func IsStaticKind(kind string) bool {
|
||||
staticKinds := map[string]bool{
|
||||
"Service": true,
|
||||
"ConfigMap": true,
|
||||
"Secret": true,
|
||||
"PersistentVolumeClaim": true,
|
||||
"PersistentVolume": true,
|
||||
"StorageClass": true,
|
||||
"Namespace": true,
|
||||
"ResourceQuota": true,
|
||||
"LimitRange": true,
|
||||
"PriorityClass": true,
|
||||
"ServiceAccount": true,
|
||||
"Role": true,
|
||||
"RoleBinding": true,
|
||||
"ClusterRole": true,
|
||||
"ClusterRoleBinding": true,
|
||||
"NetworkPolicy": true,
|
||||
"Ingress": true,
|
||||
"CustomResourceDefinition": true,
|
||||
}
|
||||
return staticKinds[kind]
|
||||
}
|
||||
|
||||
func IsStaticKindWithConfig(kind string, config *TrackConfig) bool {
|
||||
if config == nil {
|
||||
return IsStaticKind(kind)
|
||||
}
|
||||
|
||||
if len(config.CustomStaticKinds) > 0 {
|
||||
for _, customKind := range config.CustomStaticKinds {
|
||||
if kind == customKind {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return IsStaticKind(kind)
|
||||
}
|
||||
|
||||
func GetHelmReleaseLabels(releaseName, releaseNamespace string) map[string]string {
|
||||
return map[string]string{
|
||||
"meta.helm.sh/release-name": releaseName,
|
||||
"meta.helm.sh/release-namespace": releaseNamespace,
|
||||
}
|
||||
}
|
||||
|
||||
func GetHelmReleaseAnnotations(releaseName string) map[string]string {
|
||||
return map[string]string{
|
||||
"meta.helm.sh/release-name": releaseName,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
package cluster
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const testManifest = `---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
app: myapp
|
||||
ports:
|
||||
- port: 80
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: my-deployment
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: nginx:latest
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: my-config
|
||||
namespace: default
|
||||
data:
|
||||
key: value
|
||||
`
|
||||
|
||||
const emptyManifest = `---
|
||||
# Empty manifest
|
||||
`
|
||||
|
||||
const malformedManifest = `
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
namespace: default
|
||||
spec:
|
||||
invalid: [unclosed
|
||||
`
|
||||
|
||||
func TestGetReleaseResourcesFromManifest(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
manifest []byte
|
||||
releaseName string
|
||||
releaseNamespace string
|
||||
expectedCount int
|
||||
expectedKinds []string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid manifest",
|
||||
manifest: []byte(testManifest),
|
||||
releaseName: "my-release",
|
||||
releaseNamespace: "default",
|
||||
expectedCount: 3,
|
||||
expectedKinds: []string{"Service", "Deployment", "ConfigMap"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "empty manifest",
|
||||
manifest: []byte(emptyManifest),
|
||||
releaseName: "my-release",
|
||||
releaseNamespace: "default",
|
||||
expectedCount: 0,
|
||||
expectedKinds: []string{},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "nil manifest",
|
||||
manifest: nil,
|
||||
releaseName: "my-release",
|
||||
releaseNamespace: "default",
|
||||
expectedCount: 0,
|
||||
expectedKinds: []string{},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
resources, err := GetReleaseResourcesFromManifest(tt.manifest, tt.releaseName, tt.releaseNamespace)
|
||||
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, resources)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resources)
|
||||
|
||||
assert.Equal(t, tt.releaseName, resources.ReleaseName)
|
||||
assert.Equal(t, tt.releaseNamespace, resources.Namespace)
|
||||
assert.Len(t, resources.Resources, tt.expectedCount)
|
||||
|
||||
if tt.expectedKinds != nil {
|
||||
actualKinds := make([]string, len(resources.Resources))
|
||||
for i, res := range resources.Resources {
|
||||
actualKinds[i] = res.Kind
|
||||
}
|
||||
assert.ElementsMatch(t, tt.expectedKinds, actualKinds)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetReleaseResourcesFromManifestWithLogger(t *testing.T) {
|
||||
logger := zap.NewNop().Sugar()
|
||||
resources, err := GetReleaseResourcesFromManifestWithLogger(logger, []byte(testManifest), "my-release", "default", nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resources)
|
||||
|
||||
assert.Equal(t, "my-release", resources.ReleaseName)
|
||||
assert.Equal(t, "default", resources.Namespace)
|
||||
assert.Len(t, resources.Resources, 3)
|
||||
|
||||
assert.Contains(t, []string{"Service", "Deployment", "ConfigMap"}, resources.Resources[0].Kind)
|
||||
}
|
||||
|
||||
func TestIsTrackableKind(t *testing.T) {
|
||||
tests := []struct {
|
||||
kind string
|
||||
expected bool
|
||||
}{
|
||||
{"Deployment", true},
|
||||
{"StatefulSet", true},
|
||||
{"DaemonSet", true},
|
||||
{"Job", true},
|
||||
{"Pod", true},
|
||||
{"ReplicaSet", true},
|
||||
{"Service", false},
|
||||
{"ConfigMap", false},
|
||||
{"Secret", false},
|
||||
{"Ingress", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.kind, func(t *testing.T) {
|
||||
result := IsTrackableKind(tt.kind)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsStaticKind(t *testing.T) {
|
||||
tests := []struct {
|
||||
kind string
|
||||
expected bool
|
||||
}{
|
||||
{"Service", true},
|
||||
{"ConfigMap", true},
|
||||
{"Secret", true},
|
||||
{"PersistentVolumeClaim", true},
|
||||
{"Ingress", true},
|
||||
{"Deployment", false},
|
||||
{"StatefulSet", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.kind, func(t *testing.T) {
|
||||
result := IsStaticKind(tt.kind)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHelmReleaseLabels(t *testing.T) {
|
||||
labels := GetHelmReleaseLabels("my-release", "my-namespace")
|
||||
|
||||
expectedLabels := map[string]string{
|
||||
"meta.helm.sh/release-name": "my-release",
|
||||
"meta.helm.sh/release-namespace": "my-namespace",
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedLabels, labels)
|
||||
}
|
||||
|
||||
func TestGetHelmReleaseAnnotations(t *testing.T) {
|
||||
annotations := GetHelmReleaseAnnotations("my-release")
|
||||
|
||||
expectedAnnotations := map[string]string{
|
||||
"meta.helm.sh/release-name": "my-release",
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedAnnotations, annotations)
|
||||
}
|
||||
|
||||
func TestParseManifest(t *testing.T) {
|
||||
resources, err := parseManifest([]byte(testManifest), nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, resources, 3)
|
||||
|
||||
assert.Equal(t, "Service", resources[0].Kind)
|
||||
assert.Equal(t, "my-service", resources[0].Name)
|
||||
assert.Equal(t, "default", resources[0].Namespace)
|
||||
|
||||
assert.Equal(t, "Deployment", resources[1].Kind)
|
||||
assert.Equal(t, "my-deployment", resources[1].Name)
|
||||
|
||||
assert.Equal(t, "ConfigMap", resources[2].Kind)
|
||||
assert.Equal(t, "my-config", resources[2].Name)
|
||||
}
|
||||
|
||||
func TestParseManifest_Empty(t *testing.T) {
|
||||
resources, err := parseManifest([]byte(emptyManifest), nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, resources)
|
||||
}
|
||||
|
||||
func TestParseManifest_Nil(t *testing.T) {
|
||||
resources, err := parseManifest(nil, nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, resources)
|
||||
}
|
||||
|
||||
func TestResource_ManifestContent(t *testing.T) {
|
||||
resources, err := parseManifest([]byte(testManifest), nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resources, 3)
|
||||
|
||||
for _, res := range resources {
|
||||
assert.NotEmpty(t, res.Manifest)
|
||||
assert.Contains(t, res.Manifest, "apiVersion")
|
||||
assert.Contains(t, res.Manifest, "kind")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrackConfig_TrackKinds(t *testing.T) {
|
||||
config := &TrackConfig{
|
||||
TrackKinds: []string{"Deployment"},
|
||||
}
|
||||
|
||||
resources, err := GetReleaseResourcesFromManifestWithConfig(
|
||||
[]byte(testManifest),
|
||||
"test-release",
|
||||
"default",
|
||||
config,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resources)
|
||||
|
||||
assert.Len(t, resources.Resources, 1)
|
||||
assert.Equal(t, "Deployment", resources.Resources[0].Kind)
|
||||
assert.Equal(t, "my-deployment", resources.Resources[0].Name)
|
||||
}
|
||||
|
||||
func TestTrackConfig_SkipKinds(t *testing.T) {
|
||||
config := &TrackConfig{
|
||||
SkipKinds: []string{"ConfigMap"},
|
||||
}
|
||||
|
||||
resources, err := GetReleaseResourcesFromManifestWithConfig(
|
||||
[]byte(testManifest),
|
||||
"test-release",
|
||||
"default",
|
||||
config,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resources)
|
||||
|
||||
assert.Len(t, resources.Resources, 2)
|
||||
|
||||
kinds := make([]string, len(resources.Resources))
|
||||
for i, res := range resources.Resources {
|
||||
kinds[i] = res.Kind
|
||||
}
|
||||
assert.NotContains(t, kinds, "ConfigMap")
|
||||
}
|
||||
|
||||
func TestTrackConfig_CustomTrackableKinds(t *testing.T) {
|
||||
config := &TrackConfig{
|
||||
CustomTrackableKinds: []string{"CronJob"},
|
||||
}
|
||||
|
||||
isTrackable := IsTrackableKindWithConfig("CronJob", config)
|
||||
assert.True(t, isTrackable)
|
||||
|
||||
isNotTrackable := IsTrackableKindWithConfig("Deployment", config)
|
||||
assert.False(t, isNotTrackable)
|
||||
}
|
||||
|
||||
func TestTrackConfig_CustomStaticKinds(t *testing.T) {
|
||||
config := &TrackConfig{
|
||||
CustomStaticKinds: []string{"CustomResource"},
|
||||
}
|
||||
|
||||
isStatic := IsStaticKindWithConfig("CustomResource", config)
|
||||
assert.True(t, isStatic)
|
||||
|
||||
isNotStatic := IsStaticKindWithConfig("ConfigMap", config)
|
||||
assert.False(t, isNotStatic)
|
||||
}
|
||||
|
||||
func TestTrackConfig_Combined(t *testing.T) {
|
||||
config := &TrackConfig{
|
||||
SkipKinds: []string{"ConfigMap"},
|
||||
CustomTrackableKinds: []string{"CronJob"},
|
||||
CustomStaticKinds: []string{"CustomResource"},
|
||||
}
|
||||
|
||||
trackable1 := IsTrackableKindWithConfig("CronJob", config)
|
||||
assert.True(t, trackable1)
|
||||
|
||||
defaultTrackable := IsTrackableKindWithConfig("Service", config)
|
||||
assert.False(t, defaultTrackable, "Service is default trackable, but CustomTrackableKinds is configured, so it should not be trackable")
|
||||
|
||||
static1 := IsStaticKindWithConfig("CustomResource", config)
|
||||
assert.True(t, static1)
|
||||
|
||||
defaultStatic := IsStaticKindWithConfig("ConfigMap", config)
|
||||
assert.False(t, defaultStatic, "ConfigMap is default static, but CustomStaticKinds is configured, so it should not be static")
|
||||
}
|
||||
Loading…
Reference in New Issue