Skip to content

Commit

Permalink
feat: Surface App resources associated to a deploy
Browse files Browse the repository at this point in the history
- Uses kapp metadata file to list on the AppCR status the app label, namespaces and GK's
  • Loading branch information
DennisDenuto committed Aug 3, 2022
1 parent 5a1e9bb commit fd08e99
Show file tree
Hide file tree
Showing 14 changed files with 335 additions and 3 deletions.
54 changes: 54 additions & 0 deletions config/crds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,33 @@ spec:
type: integer
finished:
type: boolean
kapp:
description: KappDeployStatus contains the associated AppCR deployed resources
properties:
associatedResources:
description: AssociatedResources contains the associated App label, namespaces and GKs
properties:
groupKinds:
items:
description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types
properties:
group:
type: string
kind:
type: string
required:
- group
- kind
type: object
type: array
label:
type: string
namespaces:
items:
type: string
type: array
type: object
type: object
startedAt:
format: date-time
type: string
Expand Down Expand Up @@ -1644,6 +1671,33 @@ spec:
type: integer
finished:
type: boolean
kapp:
description: KappDeployStatus contains the associated AppCR deployed resources
properties:
associatedResources:
description: AssociatedResources contains the associated App label, namespaces and GKs
properties:
groupKinds:
items:
description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types
properties:
group:
type: string
kind:
type: string
required:
- group
- kind
type: object
type: array
label:
type: string
namespaces:
items:
type: string
type: array
type: object
type: object
startedAt:
format: date-time
type: string
Expand Down
16 changes: 16 additions & 0 deletions pkg/apis/kappctrl/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,22 @@ type AppStatusDeploy struct {
StartedAt metav1.Time `json:"startedAt,omitempty"`
// +optional
UpdatedAt metav1.Time `json:"updatedAt,omitempty"`
// +optional
KappDeployStatus KappDeployStatus `json:"kapp,omitempty"`
}

// KappDeployStatus contains the associated AppCR deployed resources
// +protobuf=false
type KappDeployStatus struct {
AssociatedResources AssociatedResources `json:"associatedResources,omitempty"`
}

// AssociatedResources contains the associated App label, namespaces and GKs
// +protobuf=false
type AssociatedResources struct {
Label string `json:"label,omitempty"`
Namespaces []string `json:"namespaces,omitempty"`
GroupKinds []metav1.GroupKind `json:"groupKinds,omitempty"`
}

// +protobuf=false
Expand Down
44 changes: 44 additions & 0 deletions pkg/apis/kappctrl/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type App struct {

pendingStatusUpdate bool
flushAllStatusUpdates bool
Metadata *Meta
}

func NewApp(app v1alpha1.App, hooks Hooks,
Expand Down
35 changes: 35 additions & 0 deletions pkg/app/app_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/vmware-tanzu/carvel-kapp-controller/pkg/apis/kappctrl/v1alpha1"
ctldep "github.com/vmware-tanzu/carvel-kapp-controller/pkg/deploy"
"github.com/vmware-tanzu/carvel-kapp-controller/pkg/exec"
"sigs.k8s.io/yaml"
)

func (a *App) deploy(tplOutput string, changedFunc func(exec.CmdRunResult)) exec.CmdRunResult {
Expand All @@ -35,6 +36,7 @@ func (a *App) deploy(tplOutput string, changedFunc func(exec.CmdRunResult)) exec
}

result = kapp.Deploy(tplOutput, a.startFlushingAllStatusUpdates, changedFunc)
a.tryCacheMetadata(kapp)

default:
result.AttachErrorf("%s", fmt.Errorf("Unsupported way to deploy"))
Expand Down Expand Up @@ -122,6 +124,39 @@ func (a *App) inspect() exec.CmdRunResult {
return result
}

// Meta contains app meta allowing for an AppCR to surface the associated namespaces and GKs
type Meta struct {
LabelKey string `yaml:"labelKey"`
LabelValue string `yaml:"labelValue"`
LastChange struct {
Namespaces []string `yaml:"namespaces"`
} `yaml:"lastChange"`
UsedGKs []struct {
Group string `yaml:"Group"`
Kind string `yaml:"Kind"`
} `yaml:"usedGKs"`
}

// tryCacheMetadata if unable to cache the kapp configmap into an App meta continue and do not fail the deploy.
func (a *App) tryCacheMetadata(kapp *ctldep.Kapp) {
if a.Metadata != nil {
return
}

cm, err := kapp.InternalAppConfigMap()
if err != nil {
return
}

appMetadata := Meta{}
err = yaml.Unmarshal([]byte(cm.Data["spec"]), &appMetadata)
if err != nil {
return
}

a.Metadata = &appMetadata
}

func (a *App) newKapp(kapp v1alpha1.AppDeployKapp, cancelCh chan struct{}) (*ctldep.Kapp, error) {
genericOpts := ctldep.GenericOpts{Name: a.app.Name, Namespace: a.app.Namespace}

Expand Down
23 changes: 22 additions & 1 deletion pkg/app/app_reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,28 @@ func (a *App) updateLastDeploy(result exec.CmdRunResult) exec.CmdRunResult {
UpdatedAt: metav1.NewTime(time.Now().UTC()),
}

a.updateStatus("marking last deploy")
defer func() {
a.updateStatus("marking last deploy")
}()

if a.Metadata == nil {
return result
}

usedGKs := []metav1.GroupKind{}
for _, gk := range a.Metadata.UsedGKs {
usedGKs = append(usedGKs, metav1.GroupKind{
gk.Group, gk.Kind,
})
}

a.app.Status.Deploy.KappDeployStatus = v1alpha1.KappDeployStatus{
AssociatedResources: v1alpha1.AssociatedResources{
Label: fmt.Sprintf("%v=%v", a.Metadata.LabelKey, a.Metadata.LabelValue),
Namespaces: a.Metadata.LastChange.Namespaces,
GroupKinds: usedGKs,
},
}

return result
}
Expand Down
33 changes: 31 additions & 2 deletions pkg/deploy/kapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package deploy

import (
"bytes"
"errors"
"fmt"
"os"
goexec "os/exec"
Expand All @@ -13,6 +14,7 @@ import (

"github.com/vmware-tanzu/carvel-kapp-controller/pkg/apis/kappctrl/v1alpha1"
"github.com/vmware-tanzu/carvel-kapp-controller/pkg/exec"
corev1 "k8s.io/api/core/v1"
)

const (
Expand All @@ -28,6 +30,7 @@ type Kapp struct {
globalDeployRawOpts []string
cancelCh chan struct{}
cmdRunner exec.CmdRunner
appConfigMap *corev1.ConfigMap
}

var _ Deploy = &Kapp{}
Expand All @@ -38,15 +41,20 @@ var _ Deploy = &Kapp{}
func NewKapp(appSuffix string, opts v1alpha1.AppDeployKapp, genericOpts ProcessedGenericOpts,
globalDeployRawOpts []string, cancelCh chan struct{}, cmdRunner exec.CmdRunner) *Kapp {

return &Kapp{appSuffix, opts, genericOpts, globalDeployRawOpts, cancelCh, cmdRunner}
return &Kapp{appSuffix, opts, genericOpts, globalDeployRawOpts, cancelCh, cmdRunner, nil}
}

// Deploy takes the output from templating, and the app name,
// it shells out, running kapp deploy ...
func (a *Kapp) Deploy(tplOutput string, startedApplyingFunc func(),
changedFunc func(exec.CmdRunResult)) exec.CmdRunResult {

args, err := a.addDeployArgs([]string{"deploy", "--prev-app", a.oldManagedName(), "-f", "-"})
metadataFile := fmt.Sprintf("/etc/kappctrl-mem-tmp/metadata-%s", a.genericOpts.Name)
defer func() {
os.Remove(metadataFile)
}()

args, err := a.addDeployArgs([]string{"deploy", "--app-metadata-file-output", metadataFile, "--prev-app", a.oldManagedName(), "-f", "-"})
if err != nil {
return exec.NewCmdRunResultWithErr(err)
}
Expand All @@ -65,6 +73,8 @@ func (a *Kapp) Deploy(tplOutput string, startedApplyingFunc func(),
result := resultBuf.Copy()
result.AttachErrorf("Deploying: %s", err)

a.tryCacheAppConfigMap(metadataFile)

return result
}

Expand Down Expand Up @@ -125,6 +135,15 @@ func (a *Kapp) Inspect() exec.CmdRunResult {
return result
}

// InternalAppConfigMap exposes the internal configmap kapp maintains on every app deploy
func (a *Kapp) InternalAppConfigMap() (*corev1.ConfigMap, error) {
if a.appConfigMap == nil {
return nil, errors.New("Unable to retrieve kapp internal config map")
}

return a.appConfigMap, nil
}

func (a *Kapp) trackCmdOutput(cmd *goexec.Cmd, startedApplyingFunc func(),
changedFunc func(exec.CmdRunResult)) (*CmdRunResultBuffer, chan struct{}) {

Expand Down Expand Up @@ -231,3 +250,13 @@ func (a *Kapp) addGenericArgs(args []string, appName string) ([]string, []string

return args, env
}

// tryCacheAppConfigMap if unable to cache the kapp configmap continue and do not fail the deploy.
func (a *Kapp) tryCacheAppConfigMap(metadataFileName string) {
metadataFile, err := os.ReadFile(metadataFileName)
if err != nil {
return
}

a.appConfigMap = &corev1.ConfigMap{Data: map[string]string{"spec": string(metadataFile)}}
}

0 comments on commit fd08e99

Please sign in to comment.