Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample config file generation #43

Merged
merged 8 commits into from
Aug 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions bin/build_templates.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash

# Copyright 2020 Google LLC
#
# 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.

#
# If you change any templates:
# 1. run this script to generate templates.go
# 2. run `go mod tidy` to remove the go-bindata dep from your mod and sum files
# 3. check in your changes
#

SCRIPTPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
ROOTDIR="$(dirname "$SCRIPTPATH")"

if [[ `command -v go-bindata` == "" ]]; then
echo "go-bindata not installed, installing..."
go get -u github.com/go-bindata/go-bindata/...
fi

TEMP_DIR=$(mktemp -d)
TEMPLATES_SOURCE_DIR="${ROOTDIR}/templates"
TEMPLATES_DIR="${TEMP_DIR}/templates"

if [ ! -d "${TEMPLATES_DIR}" ]; then
mkdir -p "${TEMPLATES_DIR}"
fi


cp -r "${TEMPLATES_SOURCE_DIR}/native" $TEMPLATES_DIR
cp -r "${TEMPLATES_SOURCE_DIR}/istio-1.6" $TEMPLATES_DIR
cp -r "${TEMPLATES_SOURCE_DIR}/istio-1.7" $TEMPLATES_DIR

# create resource
RESOURCE_FILE="${ROOTDIR}/templates/templates.go"
echo "building ${RESOURCE_FILE}"
cd ${TEMP_DIR}
echo $(ls "${TEMP_DIR}/templates")
go-bindata -nomemcopy -pkg "templates" -prefix "templates" -o "${RESOURCE_FILE}" templates/...

echo "done"
6 changes: 3 additions & 3 deletions cmd/provision/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ func (p *provision) checkRuntimeVersion(config *server.Config, client *http.Clie
}

func (p *provision) encodeUDCAEndpoint(config *server.Config, verbosef shared.FormatFn) {
config.Analytics.FluentdEndpoint = fmt.Sprintf(fluentdInternalEncodedFormat, envScopeEncodedName(p.Org, p.Env), p.Namespace)
config.Analytics.FluentdEndpoint = fmt.Sprintf(fluentdInternalEncodedFormat, EnvScopeEncodedName(p.Org, p.Env), p.Namespace)
verbosef("UDCA endpoint encoded")
}

Expand All @@ -213,8 +213,8 @@ func shortSha(s string) string {
return sha[:7]
}

// envScopeEncodedName returns the encoded resource name to avoid the 63 chars limit
func envScopeEncodedName(org, env string) string {
// EnvScopeEncodedName returns the encoded resource name to avoid the 63 chars limit
func EnvScopeEncodedName(org, env string) string {
sha := shortSha(fmt.Sprintf("%s:%s", org, env))
return fmt.Sprintf("%s-%s-%s", shortName(org), shortName(env), sha)
}
2 changes: 1 addition & 1 deletion cmd/provision/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestEncodedName(t *testing.T) {
org := "thisorgnameistoolong"
env := "thisenvnameisevenworse"
want := "thisorgnameisto-thisenvnameisev-fe4ea4e"
got := envScopeEncodedName(org, env)
got := EnvScopeEncodedName(org, env)
if got != want {
t.Errorf("encoding is incorrect, want %s, got %s", want, got)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func version(rootArgs *shared.RootArgs, printf shared.FormatFn) *cobra.Command {
}

subC.PersistentFlags().StringVarP(&rootArgs.ConfigPath, "config", "c",
"", "Path to Apigee Remote Service config file")
"", "path to Apigee Remote Service config file")

subC.PersistentFlags().StringVarP(&rootArgs.RuntimeBase, "runtime", "r",
"", "Apigee runtime base URL")
Expand Down
209 changes: 209 additions & 0 deletions cmd/samples/samples.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
// Copyright 2020 Google LLC
//
// 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 samples

import (
"fmt"
"io/ioutil"
"net/url"
"os"
"path"
"strings"
"text/template"

"github.com/apigee/apigee-remote-service-cli/cmd/provision"
"github.com/apigee/apigee-remote-service-cli/shared"
"github.com/apigee/apigee-remote-service-cli/templates"
"github.com/apigee/apigee-remote-service-envoy/server"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

type samples struct {
*shared.RootArgs
template string
outDir string
overwrite bool
RuntimeHost string
TargetService targetService
TLS tls
EncodedName string
}

type targetService struct {
Name string
Host string
}

type tls struct {
Dir string
Key string
Crt string
}

// Cmd returns base command
func Cmd(rootArgs *shared.RootArgs, printf shared.FormatFn) *cobra.Command {
s := &samples{
RootArgs: rootArgs,
TargetService: targetService{},
TLS: tls{},
}

c := &cobra.Command{
Use: "samples",
Short: "Managing sample configuration files for remote-service deployment",
Long: `Managing sample configuration files for remote-service deployment`,
Args: cobra.NoArgs,
}

c.AddCommand(cmdCreateSampleConfig(s, printf))

return c
}

func cmdCreateSampleConfig(s *samples, printf shared.FormatFn) *cobra.Command {
c := &cobra.Command{
Use: "create",
Short: "create sample configuration files for native envoy or istio",
Long: `create sample configuration files for native envoy or istio. A valid config
yaml file generated through provisioning is required via --config/-c. Files will be in
the directory specified via --out (default ./samples).
In the case of native envoy, it takes the target service host and the desired name for
its cluster. It also sets custom SSL connection from the envoy to the remote-service
cluster if a folder containing tls.key and tls.crt is provided via --tls.
In the case of istio where envoy proxy acts as sidecars, if the target is unspecified,
the httpbin example will be generated. Otherwise, users are responsible for preparing
files related to deployment of their target services.`,
Args: cobra.NoArgs,

RunE: func(cmd *cobra.Command, _ []string) error {
err := s.loadConfig()
if err != nil {
return errors.Wrap(err, "loading config yaml file")
}
err = s.createSampleConfigs(printf)
if err != nil {
return errors.Wrap(err, "creating sample config files")
}
printf("config files successfully generated.")
if s.template != "native" {
printf("please enable istio sidecar injection on the default namespace before running kubectl apply on the directory with config files.")
}
return nil
},
}

c.Flags().StringVarP(&s.ConfigPath, "config", "c", "", "path to Apigee Remote Service config file")
c.Flags().StringVarP(&s.template, "template", "t", "istio-1.6", "template name (options are istio-1.6, istio-1.7, native)")
c.Flags().BoolVarP(&s.overwrite, "force", "f", false, "force overwriting existing directory")
c.Flags().StringVarP(&s.outDir, "out", "", "./samples", "directory to create config files within")
c.Flags().StringVarP(&s.TargetService.Name, "name", "n", "httpbin", "target service name")
c.Flags().StringVarP(&s.TargetService.Host, "host", "", "httpbin.org", "target service host")
c.Flags().StringVarP(&s.TLS.Dir, "tls", "", "", "directory for tls key and crt")

_ = c.MarkFlagRequired("config")

return c
}

func (s *samples) loadConfig() error {
s.ServerConfig = &server.Config{}
err := s.ServerConfig.Load(s.ConfigPath, "")
if err != nil {
return err
}

s.RuntimeBase = strings.Split(s.ServerConfig.Tenant.RemoteServiceAPI, "/remote-service")[0]
url, err := url.Parse(s.RuntimeBase)
if err != nil {
return err
}
s.RuntimeHost = url.Hostname()
s.Org = s.ServerConfig.Tenant.OrgName
s.Env = s.ServerConfig.Tenant.EnvName
s.Namespace = s.ServerConfig.Global.Namespace
s.EncodedName = provision.EnvScopeEncodedName(s.Org, s.Env)

if s.TLS.Dir != "" {
s.TLS.Key = path.Join(s.TLS.Dir, "tls.key")
s.TLS.Crt = path.Join(s.TLS.Dir, "tls.crt")
}

return nil
}

func (s *samples) createSampleConfigs(printf shared.FormatFn) error {
_, err := ioutil.ReadDir(s.outDir)
if err != nil {
if err := os.Mkdir(s.outDir, 0755); err != nil {
return err
}
} else if s.overwrite {
printf("overwriting the existing directory...")
} else {
return fmt.Errorf("output directory already exists")
}
printf("generating %s configuration files...", s.template)
return s.createConfig(s.template, printf)
}

func (s *samples) createConfig(templateDir string, printf shared.FormatFn) error {
tempDir, err := ioutil.TempDir("", "apigee")
if err != nil {
return errors.Wrap(err, "creating temp dir")
}
defer os.RemoveAll(tempDir)

err = getTemplates(tempDir, templateDir)
if err != nil {
return errors.Wrap(err, "getting templates")
}
path := path.Join(tempDir, templateDir)
templates, err := ioutil.ReadDir(path)
if err != nil {
return errors.Wrap(err, "getting templates directory")
}
for _, f := range templates {
if f.Name() == "httpbin.yaml" && s.TargetService.Name != "httpbin" {
continue
}
err := s.createConfigYaml(path, f.Name(), printf)
if err != nil {
return err
}
}
return nil
}

func (s *samples) createConfigYaml(dir string, name string, printf shared.FormatFn) error {
tmpl, err := template.New(name).ParseFiles(path.Join(dir, name))
if err != nil {
return err
}
f, err := os.OpenFile(path.Join(s.outDir, name), os.O_WRONLY|os.O_CREATE, 0755)
if err != nil {
return err
}
printf("generating %s...", name)
return tmpl.Execute(f, s)
}

// getTemplates unzips the templates to the tempDir/templates and returns the directory
func getTemplates(tempDir string, name string) error {
if err := templates.RestoreAssets(tempDir, name); err != nil {
return errors.Wrapf(err, "restoring asset %s", name)
}
return nil
}
Loading