From 882edecb057bb517f41fad1de51c84c2bd5bd500 Mon Sep 17 00:00:00 2001 From: Ashley Jeffs Date: Fri, 13 Dec 2024 14:54:34 +0000 Subject: [PATCH] Add public license package --- CHANGELOG.md | 4 ++++ internal/license/service.go | 28 +++++++++++++++++++++++++ public/license/license.go | 42 +++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 public/license/license.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 912cd225a7..0c1cf6bf23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. ## 4.44.0 - TBD +### Added + +- Go API: New `public/license` package added to allow custom programmatic instantiations of Redpanda Connect to run enterprise license components. (@Jeffail) + ### Fixed - `gcp_bigquery` output with parquet format no longer returns errors incorrectly. (@rockwotj) diff --git a/internal/license/service.go b/internal/license/service.go index 2d88fa5a31..f66b8d99b3 100644 --- a/internal/license/service.go +++ b/internal/license/service.go @@ -103,6 +103,34 @@ func InjectTestService(res *service.Resources) { setSharedService(res, s) } +// InjectCustomLicenseBytes attempts to parse a Redpanda Enterprise license +// from a slice of bytes and, if successful, stores it within the provided +// resources pointer for enterprise components to reference. +func InjectCustomLicenseBytes(res *service.Resources, licenseBytes []byte) error { + s := &Service{ + logger: res.Logger(), + loadedLicense: &atomic.Pointer[RedpandaLicense]{}, + } + + license, err := s.validateLicense(licenseBytes) + if err != nil { + return fmt.Errorf("failed to validate license: %w", err) + } + + if err := license.CheckExpiry(); err != nil { + return err + } + + s.logger.With( + "license_org", license.Organization, + "license_type", typeDisplayName(license.Type), + "expires_at", time.Unix(license.Expiry, 0).Format(time.RFC3339), + ).Debug("Successfully loaded Redpanda license") + + s.loadedLicense.Store(&license) + return nil +} + func (s *Service) readAndValidateLicense() (RedpandaLicense, error) { licenseBytes, err := s.readLicense() if err != nil { diff --git a/public/license/license.go b/public/license/license.go new file mode 100644 index 0000000000..c44b1c36d3 --- /dev/null +++ b/public/license/license.go @@ -0,0 +1,42 @@ +// Copyright 2024 Redpanda Data, Inc. +// +// Licensed as a Redpanda Enterprise file under the Redpanda Community +// License (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// https://github.com/redpanda-data/connect/blob/main/licenses/rcl.md + +package license + +import ( + "github.com/redpanda-data/benthos/v4/public/service" + + "github.com/redpanda-data/connect/v4/internal/license" +) + +// LocateLicenseOptBuilder represents options specified for a license locator. +type LocateLicenseOptBuilder struct { + c license.Config +} + +// LocateLicenseOptFunc defines an option to pass through the LocateLicense +// function call in order to customize its behavior. +type LocateLicenseOptFunc func(*LocateLicenseOptBuilder) + +// LocateLicense attempts to locate a Redpanda Enteprise license from the +// environment and, if successful, enriches the provided resources with +// information of this license that enterprise components may reference. +func LocateLicense(res *service.Resources, opts ...LocateLicenseOptFunc) { + optBuilder := LocateLicenseOptBuilder{} + for _, o := range opts { + o(&optBuilder) + } + license.RegisterService(res, optBuilder.c) +} + +// StoreCustomLicenseBytes attempts to parse a Redpanda Enterprise license +// from a slice of bytes and, if successful, stores it within the provided +// resources pointer for enterprise components to reference. +func StoreCustomLicenseBytes(res *service.Resources, licenseBytes []byte) error { + return license.InjectCustomLicenseBytes(res, licenseBytes) +}