extension: Add new jaeger binary (#5278)

* extension: Add new jaeger binary

This branch adds a new jaeger binary project in the jaeger directory.
This follows the same logic as that of `linkerd install`. But as
`linkerd install` VFS logic expects charts to be present in `/charts`
directory, This command gets its own static pkg to generate its own
VFS for its chart.

This covers only the install part of the command

Signed-off-by: Tarun Pothulapati <tarunpothulapati@outlook.com>
This commit is contained in:
Tarun Pothulapati 2020-11-25 20:10:35 +05:30 committed by GitHub
parent 0f20b0572e
commit e7f4c31257
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 296 additions and 18 deletions

View File

@ -17,7 +17,9 @@ rootdir=$( cd "$bindir"/.. && pwd )
cd "$rootdir"
cd "$(pwd -P)"
target=target/cli/$(os)/linkerd
GO111MODULE=on go generate -mod=readonly ./pkg/charts/static # TODO: `go generate` does not honor -mod=readonly
# TODO: `go generate` does not honor -mod=readonly
GO111MODULE=on go generate -mod=readonly ./pkg/charts/static
GO111MODULE=on go generate -mod=readonly ./jaeger/static
root_tag=$("$bindir"/root-tag)
GO111MODULE=on CGO_ENABLED=0 go build -o $target -tags prod -mod=readonly -ldflags "-s -w -X github.com/linkerd/linkerd2/pkg/version.Version=$root_tag" ./cli
echo "$target"

View File

@ -14,6 +14,7 @@ FROM go-deps as golang-single-arch
WORKDIR /linkerd-build
COPY cli cli
COPY charts charts
COPY jaeger jaeger
COPY controller/k8s controller/k8s
COPY controller/api controller/api
@ -24,6 +25,7 @@ RUN mkdir -p /out
# Generate static templates
# TODO: `go generate` does not honor -mod=readonly
RUN go generate -mod=readonly ./pkg/charts/static
RUN go generate -mod=readonly ./jaeger/static
# Cache builds without version info
RUN CGO_ENABLED=0 GOOS=darwin go build -o /out/linkerd-darwin -tags prod -mod=readonly -ldflags "-s -w" ./cli

View File

@ -8,6 +8,7 @@ import (
"github.com/linkerd/linkerd2/pkg/charts"
cnicharts "github.com/linkerd/linkerd2/pkg/charts/cni"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/version"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@ -217,6 +218,7 @@ func renderCNIPlugin(w io.Writer, config *cniPluginOptions) error {
Namespace: controlPlaneNamespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
buf, err := chart.RenderCNI()
if err != nil {

View File

@ -12,6 +12,7 @@ import (
"github.com/linkerd/linkerd2/cli/flag"
"github.com/linkerd/linkerd2/pkg/charts"
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/healthcheck"
"github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/tree"
@ -331,6 +332,7 @@ func render(w io.Writer, values *l5dcharts.Values, stage string) error {
Name: chartutil.ValuesfileName,
},
},
Fs: static.Templates,
}
}
@ -368,6 +370,7 @@ func render(w io.Writer, values *l5dcharts.Values, stage string) error {
Namespace: controlPlaneNamespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
buf, err := chart.Render()
if err != nil {

View File

@ -8,6 +8,7 @@ import (
"github.com/linkerd/linkerd2/pkg/charts"
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/k8s"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
@ -348,7 +349,7 @@ func readValuesFile(t *testing.T, path string) []byte {
{Name: chartutil.ValuesfileName},
}
if err := charts.FilesReader(path+"/", valuesFiles); err != nil {
if err := charts.FilesReader(static.Templates, path+"/", valuesFiles); err != nil {
t.Fatal("Unexpected error", err)
}

View File

@ -14,6 +14,7 @@ import (
"github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/charts/multicluster"
mccharts "github.com/linkerd/linkerd2/pkg/charts/multicluster"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/healthcheck"
"github.com/linkerd/linkerd2/pkg/k8s"
mc "github.com/linkerd/linkerd2/pkg/multicluster"
@ -281,6 +282,7 @@ func newAllowCommand() *cobra.Command {
Namespace: controlPlaneNamespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
buf, err := chart.RenderNoPartials()
if err != nil {
@ -372,6 +374,7 @@ func newMulticlusterInstallCommand() *cobra.Command {
Namespace: controlPlaneNamespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
buf, err := chart.RenderNoPartials()
if err != nil {
@ -476,6 +479,7 @@ func newMulticlusterUninstallCommand() *cobra.Command {
Namespace: controlPlaneNamespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
buf, err := chart.RenderNoPartials()
if err != nil {
@ -695,6 +699,7 @@ func newLinkCommand() *cobra.Command {
Namespace: controlPlaneNamespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
serviceMirrorOut, err := chart.RenderNoPartials()
if err != nil {

View File

@ -8,13 +8,13 @@ import (
"strings"
"time"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/clientcmd"
"github.com/fatih/color"
"github.com/linkerd/linkerd2/cli/flag"
jaeger "github.com/linkerd/linkerd2/jaeger/cmd"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/clientcmd"
)
const (
@ -128,6 +128,9 @@ func init() {
RootCmd.AddCommand(newCmdVersion())
RootCmd.AddCommand(newCmdMulticluster())
RootCmd.AddCommand(newCmdUninstall())
// Extension Sub Commands
RootCmd.AddCommand(jaeger.NewCmdJaeger())
}
type statOptionsBase struct {

139
jaeger/cmd/install.go Normal file
View File

@ -0,0 +1,139 @@
package cmd
import (
"context"
"fmt"
"io"
"os"
"github.com/linkerd/linkerd2/jaeger/static"
jaeger "github.com/linkerd/linkerd2/jaeger/values"
"github.com/linkerd/linkerd2/pkg/charts"
"github.com/linkerd/linkerd2/pkg/healthcheck"
"github.com/linkerd/linkerd2/pkg/k8s"
"github.com/spf13/cobra"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
)
var (
templatesJaeger = []string{
"templates/namespace.yaml",
"templates/rbac.yaml",
"templates/tracing.yaml",
}
)
func newCmdInstall() *cobra.Command {
var skipChecks bool
values, err := jaeger.NewValues()
if err != nil {
fmt.Fprint(os.Stderr, err.Error())
os.Exit(1)
}
cmd := &cobra.Command{
Use: "install [flags]",
Args: cobra.NoArgs,
Short: "Output Kubernetes resources to install jaeger extension",
Long: `Output Kubernetes resources to install jaeger extension.`,
Example: ` # Default install.
linkerd jaeger install | kubectl apply -f -
# Install Jaeger extension into a non-default namespace.
linkerd jaeger install --namespace custom | kubectl apply -f -`,
RunE: func(cmd *cobra.Command, args []string) error {
if !skipChecks {
// Ensure there is a Linkerd installation.
exists, err := checkIfLinkerdExists(cmd.Context())
if err != nil {
return fmt.Errorf("could not check for Linkerd existence: %s", err)
}
if !exists {
return fmt.Errorf("could not find a Linkerd installation")
}
}
return install(os.Stdout, values)
},
}
cmd.Flags().BoolVar(
&skipChecks, "skip-checks", false,
`Skip checks for namespace existence`,
)
// TODO: Add --set flag set and also config
return cmd
}
func install(w io.Writer, values *jaeger.Values) error {
// TODO: Add any validation logic here
return render(w, values)
}
func render(w io.Writer, values *jaeger.Values) error {
// Render raw values and create chart config
rawValues, err := yaml.Marshal(values)
if err != nil {
return err
}
files := []*loader.BufferedFile{
{Name: chartutil.ChartfileName},
}
for _, template := range templatesJaeger {
files = append(files,
&loader.BufferedFile{Name: template},
)
}
chart := &charts.Chart{
Name: "jaeger",
Dir: "jaeger",
Namespace: values.Namespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
buf, err := chart.Render()
if err != nil {
return err
}
_, err = w.Write(buf.Bytes())
return err
}
func checkIfLinkerdExists(ctx context.Context) (bool, error) {
kubeAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
if err != nil {
return false, err
}
_, err = kubeAPI.CoreV1().Namespaces().Get(ctx, controlPlaneNamespace, metav1.GetOptions{})
if err != nil {
if kerrors.IsNotFound(err) {
return false, nil
}
return false, err
}
_, _, err = healthcheck.FetchCurrentConfiguration(ctx, kubeAPI, controlPlaneNamespace)
if err != nil {
if kerrors.IsNotFound(err) {
return false, nil
}
return false, err
}
return true, nil
}

61
jaeger/cmd/root.go Normal file
View File

@ -0,0 +1,61 @@
package cmd
import (
"fmt"
"regexp"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
const (
defaultLinkerdNamespace = "linkerd"
)
var (
apiAddr string // An empty value means "use the Kubernetes configuration"
controlPlaneNamespace string
kubeconfigPath string
kubeContext string
impersonate string
impersonateGroup []string
verbose bool
// These regexs are not as strict as they could be, but are a quick and dirty
// sanity check against illegal characters.
alphaNumDash = regexp.MustCompile(`^[a-zA-Z0-9-]+$`)
)
// NewCmdJaeger returns a new jeager command
func NewCmdJaeger() *cobra.Command {
jaegerCmd := &cobra.Command{
Use: "jaeger",
Short: "jaeger manages the jaeger extension of Linkerd service mesh",
Long: `jaeger manages the jaeger extension of Linkerd service mesh.`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// enable / disable logging
if verbose {
log.SetLevel(log.DebugLevel)
} else {
log.SetLevel(log.PanicLevel)
}
if !alphaNumDash.MatchString(controlPlaneNamespace) {
return fmt.Errorf("%s is not a valid namespace", controlPlaneNamespace)
}
return nil
},
}
jaegerCmd.PersistentFlags().StringVarP(&controlPlaneNamespace, "linkerd-namespace", "L", defaultLinkerdNamespace, "Namespace in which Linkerd is installed [$LINKERD_NAMESPACE]")
jaegerCmd.PersistentFlags().StringVar(&kubeconfigPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests")
jaegerCmd.PersistentFlags().StringVar(&kubeContext, "context", "", "Name of the kubeconfig context to use")
jaegerCmd.PersistentFlags().StringVar(&impersonate, "as", "", "Username to impersonate for Kubernetes operations")
jaegerCmd.PersistentFlags().StringArrayVar(&impersonateGroup, "as-group", []string{}, "Group to impersonate for Kubernetes operations")
jaegerCmd.PersistentFlags().StringVar(&apiAddr, "api-addr", "", "Override kubeconfig and communicate directly with the control plane at host:port (mostly for testing)")
jaegerCmd.PersistentFlags().BoolVar(&verbose, "verbose", false, "Turn on debug logging")
jaegerCmd.AddCommand(newCmdInstall())
return jaegerCmd
}

21
jaeger/static/generate.go Normal file
View File

@ -0,0 +1,21 @@
// +build ignore
package main
import (
"github.com/linkerd/linkerd2/jaeger/static"
"github.com/shurcooL/vfsgen"
log "github.com/sirupsen/logrus"
)
func main() {
err := vfsgen.Generate(static.Templates, vfsgen.Options{
Filename: "generated_jaeger_templates.gogen.go",
PackageName: "static",
BuildTags: "prod",
VariableName: "Templates",
})
if err != nil {
log.Fatalln(err)
}
}

View File

@ -0,0 +1,31 @@
//go:generate go run generate.go
// +build !prod
package static
import (
"net/http"
"path"
"path/filepath"
"runtime"
)
// Templates that will be rendered by `linkerd install`. This is only used on
// dev builds.
var Templates http.FileSystem = http.Dir(path.Join(getRepoRoot(), "jaeger/charts"))
// getRepoRoot returns the full path to the root of the repo. We assume this
// function is only called from the `Templates` var above, and that this source
// file lives at `pkg/charts/static`, relative to the root of the repo.
func getRepoRoot() string {
// /foo/bar/linkerd2/pkg/charts/static/templates.go
_, filename, _, _ := runtime.Caller(0)
// /foo/bar/linkerd2/pkg/charts/static
dir := filepath.Dir(filename)
// filepath.Dir returns the parent directory, so that combined with joining
// ".." walks 3 levels up the tree:
// /foo/bar/linkerd2
return filepath.Dir(path.Join(dir, ".."))
}

View File

@ -3,6 +3,7 @@ package values
import (
"fmt"
"github.com/linkerd/linkerd2/jaeger/static"
"github.com/linkerd/linkerd2/pkg/charts"
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"helm.sh/helm/v3/pkg/chart/loader"
@ -46,7 +47,7 @@ func readDefaults(chartDir string) (*Values, error) {
Name: chartutil.ValuesfileName,
}
if err := charts.ReadFile(chartDir, valuesFile); err != nil {
if err := charts.ReadFile(static.Templates, chartDir, valuesFile); err != nil {
return nil, err
}

View File

@ -2,6 +2,7 @@ package charts
import (
"bytes"
"net/http"
"path"
"strings"
@ -22,14 +23,16 @@ type Chart struct {
Namespace string
RawValues []byte
Files []*loader.BufferedFile
Fs http.FileSystem
}
func (c *Chart) render(partialsFiles []*loader.BufferedFile) (bytes.Buffer, error) {
if err := FilesReader(c.Dir+"/", c.Files); err != nil {
if err := FilesReader(c.Fs, c.Dir+"/", c.Files); err != nil {
return bytes.Buffer{}, err
}
if err := FilesReader("", partialsFiles); err != nil {
// static.Templates is used as partials are always available there
if err := FilesReader(static.Templates, "", partialsFiles); err != nil {
return bytes.Buffer{}, err
}
@ -115,12 +118,12 @@ func (c *Chart) RenderNoPartials() (bytes.Buffer, error) {
}
// ReadFile updates the buffered file with the data read from disk
func ReadFile(dir string, f *loader.BufferedFile) error {
func ReadFile(fs http.FileSystem, dir string, f *loader.BufferedFile) error {
filename := dir + f.Name
if dir == "" {
filename = filename[7:]
}
file, err := static.Templates.Open(filename)
file, err := fs.Open(filename)
if err != nil {
return err
}
@ -136,9 +139,9 @@ func ReadFile(dir string, f *loader.BufferedFile) error {
}
// FilesReader reads all the files from a directory
func FilesReader(dir string, files []*loader.BufferedFile) error {
func FilesReader(fs http.FileSystem, dir string, files []*loader.BufferedFile) error {
for _, f := range files {
if err := ReadFile(dir, f); err != nil {
if err := ReadFile(fs, dir, f); err != nil {
return err
}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/linkerd/linkerd2/pkg/charts"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/k8s"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
@ -56,7 +57,7 @@ func readDefaults(chartDir string) (*Values, error) {
file := &loader.BufferedFile{
Name: chartutil.ValuesfileName,
}
if err := charts.ReadFile(chartDir, file); err != nil {
if err := charts.ReadFile(static.Templates, chartDir, file); err != nil {
return nil, err
}
values := Values{}

View File

@ -4,14 +4,14 @@ import (
"fmt"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/imdario/mergo"
"github.com/linkerd/linkerd2/pkg/charts"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/version"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
)
@ -288,7 +288,7 @@ func readDefaults(chartDir string, ha bool) (*Values, error) {
})
}
if err := charts.FilesReader(chartDir, valuesFiles); err != nil {
if err := charts.FilesReader(static.Templates, chartDir, valuesFiles); err != nil {
return nil, err
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/linkerd/linkerd2/pkg/charts"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/k8s"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
@ -77,7 +78,7 @@ func readDefaults(chartDir string) (*Values, error) {
file := &loader.BufferedFile{
Name: chartutil.ValuesfileName,
}
if err := charts.ReadFile(chartDir, file); err != nil {
if err := charts.ReadFile(static.Templates, chartDir, file); err != nil {
return nil, err
}
values := Values{}

View File

@ -10,7 +10,7 @@ import (
func main() {
err := vfsgen.Generate(static.Templates, vfsgen.Options{
Filename: "generated_templates.gogen.go",
Filename: "generated_linkerd_templates.gogen.go",
PackageName: "static",
BuildTags: "prod",
VariableName: "Templates",

View File

@ -18,6 +18,7 @@ import (
"github.com/linkerd/linkerd2/pkg/charts"
"github.com/linkerd/linkerd2/pkg/charts/linkerd2"
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/charts/static"
"github.com/linkerd/linkerd2/pkg/k8s"
log "github.com/sirupsen/logrus"
"helm.sh/helm/v3/pkg/chart/loader"
@ -292,6 +293,7 @@ func (conf *ResourceConfig) GetPatch(injectProxy bool) ([]byte, error) {
Namespace: conf.values.GetGlobal().Namespace,
RawValues: rawValues,
Files: files,
Fs: static.Templates,
}
buf, err := chart.Render()
if err != nil {