Skip to content

Commit

Permalink
gen2 profiles aka "AppProfiles" (design proposal 3) (#335)
Browse files Browse the repository at this point in the history
Design doc: https://github.com/arlonproj/arlon/blob/private/leb/multiprofiles/docs/gen2_profiles_proposal_3.md
Testing:
- unit test located at pkg/appprofile/appprofile_test.go
- E2E test: make e2e-appprofiles

------ squashed commits ------

* gen2 profiles

* update gen2 profiles doc

* use applicationset apis from argo-cd repo

* initial AppProfile API, needs 'make' to regenerate code

* after make generate

* initial implementation of AppProfiles - untested

* fix circular import loop

* appprofiles reconciliation started working

* appprofiles reconciliation - improvements

* add application (cluster) and applicationset (app) reconciliation

* doc for gen2 profles - proposal 2

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* add arlon-gen2-profiles-reconc-algo.png

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* Update gen2_profiles_proposal_2.md

* fix reconciliation bug: don't take address of temp loop variable

* Update gen2_profiles_proposal_2.md

* multiple profiles support: initial implementation

* fixes ... seems to work now

* use a better time encoder for zap logger

* more logging tweaks to make log lines shorter

* unit test, first iteration

* unit test enhancements

* more unit test enhancements

* even more unit test enhancements

* add 'appprofile list' command

* display app-profiles in 'app list' command output

* 'appprofile list' and 'app create' commands, display app-profiles in 'app list' command output

* fix unit test

* new 'app delete' command

* display appprofiles in 'cluster list' command

* fix nil pointer deref bug in reconciliation

* new 'cluster setappprofiles' command

* new document for proposal 3 of gen2 profiles

* Update gen2_profiles_proposal_3.md

* Update gen2_profiles_proposal_3.md

* set CONTROLLER_TOOLS_VERSION to v0.10.0

* remove ngprofile and app/[add_to|remove_from]_profile commands

* Makefile: add unittests target

* add unit tests to github CI workflow

* set arlon image version to 0.10.0 in deployment yaml

* RBAC settings for appprofile

* add examples/declarative and examples/clustertemplates

* remove sshKeyName field from example cluster manifest

* rename my-cluster -> mycluster

* prepare base cluster files for examples/clustertemplates/eks-managed-mpool/manifest.yaml

* rename my-cluster -> mycluster in cluster.yaml

* consolidate example apps into single file

* raise arlon controller memory request and limit

* again raise arlon controller (the other one) memory request and limit

* fix repoUrl for redis example app

* (WIP) add e2e test for appprofiles

* fix relative path to example manifests

* fix relative path to example manifests again

* e2e-appprofiles: fix the expected values for MachinePool

* e2e-appprofiles: fix the API version for MachinePool

* Update .github/workflows/ci.yml

Co-authored-by: Rohit Rajak <[email protected]>

* Update cmd/app/create.go

remove null import of 'embed'

Co-authored-by: Rohit Rajak <[email protected]>

* Update cmd/app/delete.go

remove null import of 'embed'

Co-authored-by: Rohit Rajak <[email protected]>

* remove unittests target because pkgtest does same thing

* remove unused constant

Co-authored-by: Bich Le <[email protected]>
Co-authored-by: arlon automation <[email protected]>
Co-authored-by: Rohit Rajak <[email protected]>
  • Loading branch information
4 people authored and cruizen committed Dec 16, 2022
1 parent bcff4a5 commit 4c580cc
Show file tree
Hide file tree
Showing 59 changed files with 3,105 additions and 36 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
cache: true
- name: Build
run: go build -v ./...
- name: Unit tests
run: make pkgtest
- name: Run coverage
run: go test -race -coverprofile=coverage.txt -covermode=atomic
- name: Upload coverage to Codecov
Expand Down
24 changes: 19 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ else
GOBIN=$(shell go env GOBIN)
endif

## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)

CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen

## Tool Versions
CONTROLLER_TOOLS_VERSION ?= v0.10.0

# Setting SHELL to bash allows bash commands to be executed by recipes.
# This is a requirement for 'setup-envtest.sh' in the test target.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
Expand Down Expand Up @@ -129,10 +139,10 @@ deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/default | kubectl delete -f -


CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
controller-gen: ## Download controller-gen locally if necessary.
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.10.0)
.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
$(CONTROLLER_GEN): $(LOCALBIN)
test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)

KUSTOMIZE = $(shell pwd)/bin/kustomize
kustomize: ## Download kustomize locally if necessary.
Expand Down Expand Up @@ -165,5 +175,9 @@ test-e2e:
kubectl kuttl test --start-kind=false ./testing/e2e/ --test 05-delete
kubectl kuttl test --start-kind=false ./testing/e2e/ --test 06-manage --kind-context arlon-e2e-testbed --timeout 300

test-e2e-appprofiles:
./testing/e2e_setup.sh
kubectl kuttl test --start-kind=false ./testing/e2e-appprofiles/ --test 00-deploy

e2e-teardown:
./testing/e2e_setup_teardown.sh
./testing/e2e_setup_teardown.sh
9 changes: 9 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,13 @@ resources:
kind: Profile
path: github.com/arlonproj/arlon/api/v1
version: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: arlon.io
group: core
kind: AppProfile
path: github.com/arlonproj/arlon/api/v1
version: v1
version: "3"
68 changes: 68 additions & 0 deletions api/v1/appprofile_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Copyright 2021.
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 v1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// AppProfileSpec defines the desired state of AppProfile
type AppProfileSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

AppNames []string `json:"appNames,omitempty"`
}

// AppProfileStatus defines the observed state of AppProfile
type AppProfileStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Health values: healthy, degraded
Health string `json:"health,omitempty"`
// Names of apps that don't exist
InvalidAppNames []string `json:"invalidAppNames,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// AppProfile is the Schema for the appprofiles API
type AppProfile struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec AppProfileSpec `json:"spec,omitempty"`
Status AppProfileStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// AppProfileList contains a list of AppProfile
type AppProfileList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AppProfile `json:"items"`
}

func init() {
SchemeBuilder.Register(&AppProfile{}, &AppProfileList{})
}
99 changes: 99 additions & 0 deletions api/v1/zz_generated.deepcopy.go

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

19 changes: 19 additions & 0 deletions cmd/app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package app

import "github.com/spf13/cobra"

func NewCommand() *cobra.Command {
command := &cobra.Command{
Use: "app",
Short: "Manage apps",
Long: "Manage apps",
DisableAutoGenTag: true,
Run: func(c *cobra.Command, args []string) {
c.Usage()
},
}
command.AddCommand(listAppsCommand())
command.AddCommand(createAppCommand())
command.AddCommand(deleteAppCommand())
return command
}
81 changes: 81 additions & 0 deletions cmd/app/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package app

import (
"context"
"fmt"
appset "github.com/argoproj/argo-cd/v2/pkg/apis/applicationset/v1alpha1"
"github.com/arlonproj/arlon/pkg/app"
"github.com/arlonproj/arlon/pkg/ctrlruntimeclient"
"os"

"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/client-go/tools/clientcmd"
)

func createAppCommand() *cobra.Command {
var clientConfig clientcmd.ClientConfig
var argocdNs string
var repoUrl string
var repoRevision string
var repoPath string
var appName string
var destNs string
var project string
var outputYaml bool
var autoSync bool
var autoPrune bool
command := &cobra.Command{
Use: "create appName repoUrl repoPath [--repo-revision revision][--output-yaml][--autosync][--autoprune][other flags]",
Short: "create new Arlon app",
Long: "create new Arlon app, which is represented as a specialized ArgoCD ApplicationSet resource",
Args: cobra.ExactArgs(3),
RunE: func(c *cobra.Command, args []string) error {
appName = args[0]
repoUrl = args[1]
repoPath = args[2]
app := app.Create(argocdNs, appName, destNs, project, repoPath, repoUrl, repoRevision, autoSync, autoPrune)
if outputYaml {
scheme := runtime.NewScheme()
if err := appset.AddToScheme(scheme); err != nil {
return fmt.Errorf("failed to add scheme: %s", err)
}
s := json.NewSerializerWithOptions(json.DefaultMetaFactory,
scheme, scheme, json.SerializerOptions{
Yaml: true,
Pretty: true,
Strict: false,
})
err := s.Encode(&app, os.Stdout)
if err != nil {
return fmt.Errorf("failed to encode arlon app: %s", err)
}
} else {
config, err := clientConfig.ClientConfig()
if err != nil {
return fmt.Errorf("failed to get k8s client config: %s", err)
}
cli, err := ctrlruntimeclient.NewClient(config)
if err != nil {
return fmt.Errorf("failed to get controller runtime client: %s", err)
}
err = cli.Create(context.Background(), &app)
if err != nil {
return fmt.Errorf("failed to create resource: %s", err)
}
}
return nil
},
}
clientConfig = cli.AddKubectlFlagsToCmd(command)
command.Flags().StringVar(&argocdNs, "argocd-ns", "argocd", "the argocd namespace")
command.Flags().StringVar(&repoRevision, "repo-revision", "HEAD", "the git revision for app template")
command.Flags().StringVar(&destNs, "dest-ns", "default", "destination namespace in target cluster(s)")
command.Flags().StringVar(&project, "project", "default", "ArgoCD project for ApplicationSet representing Arlon app")
command.Flags().BoolVar(&outputYaml, "output-yaml", false, "output YAML instead of deploying to management cluster")
command.Flags().BoolVar(&autoSync, "autosync", true, "enable ArgoCD auto-sync")
command.Flags().BoolVar(&autoPrune, "autoprune", true, "enable ArgoCD auto-prune, only meaningful if auto-sync enabled")
return command
}
35 changes: 35 additions & 0 deletions cmd/app/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package app

import (
"fmt"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/arlonproj/arlon/pkg/app"
"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
)

func deleteAppCommand() *cobra.Command {
var clientConfig clientcmd.ClientConfig
var argocdNs string
var appName string
command := &cobra.Command{
Use: "delete appName",
Short: "delete existing Arlon app",
Long: "delete existing Arlon app",
Args: cobra.ExactArgs(1),
RunE: func(c *cobra.Command, args []string) error {
appName = args[0]
config, err := clientConfig.ClientConfig()
if err != nil {
return fmt.Errorf("failed to get k8s client config: %s", err)
}
if err = app.Delete(config, argocdNs, appName); err != nil {
return fmt.Errorf("failed to delete arlon app: %s", err)
}
return nil
},
}
clientConfig = cli.AddKubectlFlagsToCmd(command)
command.Flags().StringVar(&argocdNs, "argocd-ns", "argocd", "the argocd namespace")
return command
}
Loading

0 comments on commit 4c580cc

Please sign in to comment.