Skip to content

Commit 12308c6

Browse files
authored
Add k8ssandra demo support to CLI (#1367)
Summary: We want to add a K8ssandra demo to our list of demos. A few changes needed to be made to ensure the demo can be deployed properly: - We should check for cert-manager as a required dep. We decided not to deploy this with the demo, since deploying 2 cert-managers can break things. If we deploy cert-manager for the user, there's a bit of bookkeeping we'd need to do if the user runs `px demo delete` to decide whether or not we should also clean up cert-manager. Instead, we'll leave this up to the user for the time-being. - The demo deploys some CRDs. This can lead to race conditions if deploying everything in the manifest at once. To handle this, added a retry in the deploy block. Relevant Issues: #680 Type of change: /kind cleanup Test Plan: Push to dev demo manifest, `px demo deploy` with and without cert-manager installed. --------- Signed-off-by: Michelle Nguyen <michellenguyen@pixielabs.ai>
1 parent 87b7751 commit 12308c6

File tree

5 files changed

+66
-6
lines changed

5 files changed

+66
-6
lines changed

demos/BUILD.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,19 @@ pkg_tar(
4545
strip_prefix = "online-boutique",
4646
)
4747

48+
pkg_tar(
49+
name = "px-k8ssandra",
50+
srcs = glob(["k8ssandra/*"]),
51+
extension = "tar.gz",
52+
strip_prefix = "k8ssandra",
53+
)
54+
4855
ARCHIVES = [
4956
":px-finagle",
5057
":px-kafka",
5158
":px-sock-shop",
5259
":px-online-boutique",
60+
":px-k8ssandra",
5361
]
5462

5563
demo_upload(

demos/manifest.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,12 @@
4242
"Mux tracing is only enabled on newer kernels (>= 5.2) by default.",
4343
"Make sure your system meets these requirements before deploying."
4444
]
45+
},
46+
"px-k8ssandra": {
47+
"description": "Microservice demo that spins up Cassandra and the Spring PetClinic demo app.",
48+
"instructions": ["Use the px/cql_data script to view the Cassandra traffic flowing from the demo app."],
49+
"dependencies": {
50+
"cert-manager": true
51+
}
4552
}
4653
}

src/pixie_cli/pkg/cmd/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ go_library(
6666
"@com_github_alecthomas_chroma//quick",
6767
"@com_github_blang_semver//:semver",
6868
"@com_github_bmatcuk_doublestar//:doublestar",
69+
"@com_github_cenkalti_backoff_v4//:backoff",
6970
"@com_github_dustin_go_humanize//:go-humanize",
7071
"@com_github_fatih_color//:color",
7172
"@com_github_gofrs_uuid//:uuid",

src/pixie_cli/pkg/cmd/demo.go

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"strings"
3333
"time"
3434

35+
"github.com/cenkalti/backoff/v4"
3536
"github.com/fatih/color"
3637
"github.com/segmentio/analytics-go/v3"
3738
log "github.com/sirupsen/logrus"
@@ -51,6 +52,7 @@ import (
5152
const manifestFile = "manifest.json"
5253

5354
var errNamespaceAlreadyExists = errors.New("namespace already exists")
55+
var errCertMgrDoesNotExist = errors.New("cert-manager does not exist")
5456

5557
func init() {
5658
DemoCmd.PersistentFlags().String("artifacts", "https://storage.googleapis.com/pixie-prod-artifacts/prod-demo-apps", "The path to the demo apps")
@@ -324,11 +326,14 @@ func deployCmd(cmd *cobra.Command, args []string) {
324326
return
325327
}
326328

327-
err = setupDemoApp(appName, yamls)
329+
err = setupDemoApp(appName, yamls, appSpec.Dependencies)
328330
if err != nil {
329331
if errors.Is(err, errNamespaceAlreadyExists) {
330332
utils.Error("Failed to deploy demo application: namespace already exists.")
331333
return
334+
} else if errors.Is(err, errCertMgrDoesNotExist) {
335+
utils.Error("Failed to deploy demo application: cert-manager needs to be installed. To deploy, please follow instructions at https://cert-manager.io/docs/getting-started/")
336+
return
332337
}
333338
// Using log.Errorf rather than CLI log in order to track this unexpected error in Sentry.
334339
log.WithError(err).Errorf("Error deploying demo application, deleting namespace %s", appName)
@@ -351,8 +356,9 @@ func deployCmd(cmd *cobra.Command, args []string) {
351356
}
352357

353358
type manifestAppSpec struct {
354-
Description string `json:"description"`
355-
Instructions []string `json:"instructions"`
359+
Description string `json:"description"`
360+
Instructions []string `json:"instructions"`
361+
Dependencies map[string]bool `json:"dependencies"`
356362
}
357363

358364
type manifest = map[string]*manifestAppSpec
@@ -468,9 +474,40 @@ func createNamespace(namespace string) error {
468474
return err
469475
}
470476

471-
func setupDemoApp(appName string, yamls map[string][]byte) error {
477+
func certManagerExists() (bool, error) {
472478
kubeConfig := k8s.GetConfig()
473479
clientset := k8s.GetClientset(kubeConfig)
480+
481+
deps, err := clientset.AppsV1().Deployments("").List(context.Background(), metav1.ListOptions{})
482+
if err != nil {
483+
return false, err
484+
}
485+
486+
for _, d := range deps.Items {
487+
if d.Name == "cert-manager" {
488+
return true, nil
489+
}
490+
}
491+
492+
return false, err
493+
}
494+
495+
func setupDemoApp(appName string, yamls map[string][]byte, deps map[string]bool) error {
496+
kubeConfig := k8s.GetConfig()
497+
clientset := k8s.GetClientset(kubeConfig)
498+
499+
// Check deps.
500+
if deps["cert-manager"] {
501+
certMgrExists, err := certManagerExists()
502+
if err != nil && !k8s_errors.IsNotFound(err) {
503+
return err
504+
}
505+
506+
if !certMgrExists || k8s_errors.IsNotFound(err) {
507+
return errCertMgrDoesNotExist
508+
}
509+
}
510+
474511
if namespaceExists(appName) {
475512
fmt.Printf("%s: namespace %s already exists. If created with px, run %s to remove\n",
476513
color.RedString("Error"), color.RedString(appName), color.GreenString(fmt.Sprintf("px demo delete %s", appName)))
@@ -484,7 +521,14 @@ func setupDemoApp(appName string, yamls map[string][]byte) error {
484521
newTaskWrapper(fmt.Sprintf("Deploying %s YAMLs", appName), func() error {
485522
for _, yamlBytes := range yamls {
486523
yamlBytes := yamlBytes
487-
err := k8s.ApplyYAML(clientset, kubeConfig, appName, bytes.NewReader(yamlBytes), false)
524+
bo := backoff.NewExponentialBackOff()
525+
bo.MaxElapsedTime = 5 * time.Minute
526+
527+
op := func() error {
528+
return k8s.ApplyYAML(clientset, kubeConfig, appName, bytes.NewReader(yamlBytes), false)
529+
}
530+
531+
err := backoff.Retry(op, bo)
488532
if err != nil {
489533
return err
490534
}

src/utils/shared/k8s/apply.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func ApplyResources(clientset kubernetes.Interface, config *rest.Config, resourc
236236
nsRes := res.Namespace(objNS)
237237

238238
createRes := nsRes
239-
if k8sRes == "namespaces" || k8sRes == "configmap" || k8sRes == "clusterrolebindings" || k8sRes == "clusterroles" || k8sRes == "customresourcedefinitions" {
239+
if k8sRes == "validatingwebhookconfigurations" || k8sRes == "mutatingwebhookconfigurations" || k8sRes == "namespaces" || k8sRes == "configmap" || k8sRes == "clusterrolebindings" || k8sRes == "clusterroles" || k8sRes == "customresourcedefinitions" {
240240
createRes = res
241241
}
242242

0 commit comments

Comments
 (0)