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

Add option for operator to integration tests #18991

Merged
merged 2 commits into from
Nov 28, 2019
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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ require (
gopkg.in/yaml.v2 v2.2.4
istio.io/api v0.0.0-20191120195622-f0abe0c81e59
istio.io/gogo-genproto v0.0.0-20191024203824-d079cc8b1d55
istio.io/operator v0.0.0-20191121175823-9f96fae01248
istio.io/operator v0.0.0-20191122214537-480abfe34a1e
istio.io/pkg v0.0.0-20191113122952-4f521de9c8ca
k8s.io/api v0.0.0
k8s.io/apiextensions-apiserver v0.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -927,8 +927,8 @@ istio.io/gogo-genproto v0.0.0-20190930162913-45029607206a h1:w7zILua2dnYo9CxImhp
istio.io/gogo-genproto v0.0.0-20190930162913-45029607206a/go.mod h1:OzpAts7jljZceG4Vqi5/zXy/pOg1b209T3jb7Nv5wIs=
istio.io/gogo-genproto v0.0.0-20191024203824-d079cc8b1d55 h1:nvpx66mnuGvXYP4IfCWfUqB9YhiXBF3MvUDsclNnDzI=
istio.io/gogo-genproto v0.0.0-20191024203824-d079cc8b1d55/go.mod h1:OzpAts7jljZceG4Vqi5/zXy/pOg1b209T3jb7Nv5wIs=
istio.io/operator v0.0.0-20191121175823-9f96fae01248 h1:mqyL2l3zYCzDKyM8erYItIcPCgNMvRvLQL7B1JWP7Hc=
istio.io/operator v0.0.0-20191121175823-9f96fae01248/go.mod h1:aAkwaj5S0Yl3v762WBG2fz/cOP/Zd46LadvD7PQosuI=
istio.io/operator v0.0.0-20191122214537-480abfe34a1e h1:fy19pDTQfvyFJQagEs9BDowK3j1cOeK7Wx/+5AcJyfA=
istio.io/operator v0.0.0-20191122214537-480abfe34a1e/go.mod h1:aAkwaj5S0Yl3v762WBG2fz/cOP/Zd46LadvD7PQosuI=
istio.io/pkg v0.0.0-20191029184635-5c2f5ef63692 h1:MT7e5hpQ8cGtKCeWIjtdluEVkIhkN2tw4iVkAzhWHYA=
istio.io/pkg v0.0.0-20191029184635-5c2f5ef63692/go.mod h1:O7Uqtzc1w7+NiEV2TUeO2yPoR+4GlwlDgSocYZMjBfs=
istio.io/pkg v0.0.0-20191113122952-4f521de9c8ca h1:WmfXcc/AU/+r7CULqKx53YKd6I/iMe1WOYhuspjoJDM=
Expand Down
2 changes: 0 additions & 2 deletions install/kubernetes/helm/istio/test-values/values-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ mixer:
adapters:
stdio:
enabled: true
kiali:
enabled: true

sidecarInjectorWebhook:
rewriteAppHTTPProbe: true
3 changes: 1 addition & 2 deletions istioctl/pkg/multicluster/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"istio.io/api/mesh/v1alpha1"
operatorV1alpha1 "istio.io/operator/pkg/apis/istio/v1alpha1"
operatorV1alpha2 "istio.io/operator/pkg/apis/istio/v1alpha2"
"istio.io/operator/pkg/helm"
"istio.io/operator/pkg/util"
"istio.io/operator/pkg/validate"

Expand Down Expand Up @@ -151,7 +150,7 @@ func generateIstioControlPlane(mesh *Mesh, current *Cluster, meshNetworks *v1alp
if err != nil {
return "", err
}
mergedYAML, err := helm.OverlayYAML(baseYAML, overlayYAML)
mergedYAML, err := util.OverlayYAML(baseYAML, overlayYAML)
if err != nil {
return "", err
}
Expand Down
51 changes: 51 additions & 0 deletions pkg/test/framework/components/istio/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var (
PolicyNamespace: DefaultSystemNamespace,
IngressNamespace: DefaultSystemNamespace,
EgressNamespace: DefaultSystemNamespace,
Operator: false,
DeployIstio: true,
DeployTimeout: 0,
UndeployTimeout: 0,
Expand Down Expand Up @@ -115,12 +116,20 @@ type Config struct {
// The Helm values file to be used.
ValuesFile string

// Override values specifically for the ICP crd
// This is mostly required for cases where --set cannot be used
// If specified, Values will be ignored
ControlPlaneValues string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment that this will be ignored if ValuesFile is provided?


// Overrides for the Helm values file.
Values map[string]string

// Indicates that the test should deploy Istio into the target Kubernetes cluster before running tests.
DeployIstio bool

// Operator determines if we should use the operator for installation
Operator bool

// Do not wait for the validation webhook before completing the deployment. This is useful for
// doing deployments without Galley.
SkipWaitForValidationWebhook bool
Expand Down Expand Up @@ -161,6 +170,47 @@ func (c *Config) IsMtlsEnabled() bool {
return true
}

func (c *Config) IstioControlPlane() string {
data := c.ControlPlaneValues
if c.ValuesFile != "" {
var err error
data, err = file.AsString(filepath.Join(c.ChartDir, c.ValuesFile))
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log the error?

return ""
}
}
s, err := image.SettingsFromCommandLine()
if err != nil {
return ""
}

return fmt.Sprintf(`
apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
spec:
hub: %s
tag: %s
values:
%s
`, s.Hub, s.Tag, Indent(data, " "))
}

// indents a block of text with an indent string
func Indent(text, indent string) string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be public? If so, seems pretty generic ... maybe move somewhere more common?

if text[len(text)-1:] == "\n" {
result := ""
for _, j := range strings.Split(text[:len(text)-1], "\n") {
result += indent + j + "\n"
}
return result
}
result := ""
for _, j := range strings.Split(strings.TrimRight(text, "\n"), "\n") {
result += indent + j + "\n"
}
return result[:len(result)-1]
}

// DefaultConfig creates a new Config from defaults, environments variables, and command-line parameters.
func DefaultConfig(ctx resource.Context) (Config, error) {
// Make a local copy.
Expand Down Expand Up @@ -287,6 +337,7 @@ func (c *Config) String() string {
result += fmt.Sprintf("IngressNamespace: %s\n", c.IngressNamespace)
result += fmt.Sprintf("EgressNamespace: %s\n", c.EgressNamespace)
result += fmt.Sprintf("DeployIstio: %v\n", c.DeployIstio)
result += fmt.Sprintf("Operator: %v\n", c.Operator)
result += fmt.Sprintf("DeployTimeout: %s\n", c.DeployTimeout.String())
result += fmt.Sprintf("UndeployTimeout: %s\n", c.UndeployTimeout.String())
result += fmt.Sprintf("Values: %v\n", c.Values)
Expand Down
2 changes: 2 additions & 0 deletions pkg/test/framework/components/istio/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ func init() {
"Specifies the namespace in which istio egressgateway is deployed.")
flag.BoolVar(&settingsFromCommandline.DeployIstio, "istio.test.kube.deploy", settingsFromCommandline.DeployIstio,
"Deploy Istio into the target Kubernetes environment.")
flag.BoolVar(&settingsFromCommandline.Operator, "istio.test.kube.operator", settingsFromCommandline.Operator,
"Deploy Istio into the target Kubernetes environment using the operator.")
flag.DurationVar(&settingsFromCommandline.DeployTimeout, "istio.test.kube.deployTimeout", 0,
"Timeout applied to deploying Istio into the target Kubernetes environment. Only applies if DeployIstio=true.")
flag.DurationVar(&settingsFromCommandline.UndeployTimeout, "istio.test.kube.undeployTimeout", 0,
Expand Down
6 changes: 5 additions & 1 deletion pkg/test/framework/components/istio/istio.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ func Deploy(ctx resource.Context, cfg *Config) (Instance, error) {
var i Instance
switch ctx.Environment().EnvironmentName() {
case environment.Kube:
i, err = deploy(ctx, ctx.Environment().(*kube.Environment), *cfg)
if cfg.Operator {
i, err = deployOperator(ctx, ctx.Environment().(*kube.Environment), *cfg)
} else {
i, err = deploy(ctx, ctx.Environment().(*kube.Environment), *cfg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could rename deploy to deployHelm or similar

}
default:
err = resource.UnsupportedEnvironment(ctx.Environment())
}
Expand Down
183 changes: 183 additions & 0 deletions pkg/test/framework/components/istio/operator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Copyright 2019 Istio Authors
//
// 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 istio

import (
"fmt"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"

"istio.io/istio/pkg/test/deployment"
"istio.io/istio/pkg/test/framework/components/environment/kube"
"istio.io/istio/pkg/test/framework/components/istioctl"
"istio.io/istio/pkg/test/framework/core/image"
"istio.io/istio/pkg/test/framework/resource"
"istio.io/istio/pkg/test/scopes"
)

type operatorComponent struct {
id resource.ID
settings Config
ctx resource.Context
environment *kube.Environment
}

var _ io.Closer = &operatorComponent{}
var _ Instance = &operatorComponent{}
var _ resource.Dumper = &operatorComponent{}

// ID implements resource.Instance
func (i *operatorComponent) ID() resource.ID {
return i.id
}

func (i *operatorComponent) Settings() Config {
return i.settings
}

func (i *operatorComponent) Close() (err error) {
scopes.CI.Infof("=== BEGIN: Cleanup Istio ===")
defer scopes.CI.Infof("=== DONE: Cleanup Istio ===")
if i.settings.DeployIstio {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should delete using the operator as well.
Currently the method is to dump (manifest generate) into a file and kubectl delete -f that file.

An uninstall method is being worked on for 1.5, in which we can use it.

Copy link
Member Author

@howardjohn howardjohn Nov 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it work? That was the way helm was documented but the helm tests do a delete of the namespace, not sure if that was intentional. I guess testing the delete should be part of the test though, so if it doesn't work we need to fix it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep. deletion must be tested as well.
At least you can run delete and ignore the errors from kubectl.
@ostromart could give the best advise on how to delete currently.

err = i.environment.Accessor.DeleteNamespace(i.settings.SystemNamespace)
if err == nil {
err = i.environment.Accessor.WaitForNamespaceDeletion(i.settings.SystemNamespace)
}
// Note: when cleaning up an Istio deployment, ValidatingWebhookConfiguration
// and MutatingWebhookConfiguration must be cleaned up. Otherwise, next
// Istio deployment in the cluster will be impacted, causing flaky test results.
// Clean up ValidatingWebhookConfiguration, if any
_ = i.environment.DeleteValidatingWebhook(DefaultValidatingWebhookConfigurationName)
// Clean up MutatingWebhookConfiguration, if any
_ = i.environment.DeleteMutatingWebhook(DefaultMutatingWebhookConfigurationName)
}
return
}

func (i *operatorComponent) Dump() {
scopes.CI.Errorf("=== Dumping Istio Deployment State...")

d, err := i.ctx.CreateTmpDirectory("istio-state")
if err != nil {
scopes.CI.Errorf("Unable to create directory for dumping Istio contents: %v", err)
return
}

deployment.DumpPodState(d, i.settings.SystemNamespace, i.environment.Accessor)
deployment.DumpPodEvents(d, i.settings.SystemNamespace, i.environment.Accessor)

pods, err := i.environment.Accessor.GetPods(i.settings.SystemNamespace)
if err != nil {
scopes.CI.Errorf("Unable to get pods from the system namespace: %v", err)
return
}

for _, pod := range pods {
for _, container := range pod.Spec.Containers {
l, err := i.environment.Logs(pod.Namespace, pod.Name, container.Name, false /* previousLog */)
if err != nil {
scopes.CI.Errorf("Unable to get logs for pod/container: %s/%s/%s", pod.Namespace, pod.Name, container.Name)
continue
}

fname := path.Join(d, fmt.Sprintf("%s-%s.log", pod.Name, container.Name))
if err = ioutil.WriteFile(fname, []byte(l), os.ModePerm); err != nil {
scopes.CI.Errorf("Unable to write logs for pod/container: %s/%s/%s", pod.Namespace, pod.Name, container.Name)
}
}
}
}

func deployOperator(ctx resource.Context, env *kube.Environment, cfg Config) (Instance, error) {
scopes.CI.Infof("=== Istio Component Config ===")
scopes.CI.Infof("\n%s", cfg.String())
scopes.CI.Infof("================================")

i := &operatorComponent{
environment: env,
settings: cfg,
ctx: ctx,
}
i.id = ctx.TrackResource(i)

if !cfg.DeployIstio {
scopes.Framework.Info("skipping deployment due to Config")
return i, nil
}

istioCtl, err := istioctl.New(ctx, istioctl.Config{})
if err != nil {
return nil, err
}

// Top-level work dir for Istio deployment.
workDir, err := ctx.CreateTmpDirectory("istio-deployment")
if err != nil {
return nil, err
}

icpFile := filepath.Join(workDir, "icp.yaml")
if err := ioutil.WriteFile(icpFile, []byte(cfg.IstioControlPlane()), os.ModePerm); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any concern about IstioControlPlane silently failing here (and returning "")?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I think this is actually normally returning "" and then that does nothing since -f "" is a no-op. So we should probably clean up this a bit

return nil, fmt.Errorf("failed to write icp: %v", err)
}
s, err := image.SettingsFromCommandLine()
if err != nil {
return nil, err
}
cmd := []string{
"manifest", "apply",
"--skip-confirmation",
"--logtostderr",
"-f", icpFile,
"--force", // Blocked by https://github.com/istio/istio/issues/19009
"--set", "values.global.controlPlaneSecurityEnabled=false",
"--set", "values.global.imagePullPolicy=" + s.PullPolicy,
}
// If control plane values set, assume this includes the full set of values, and .Values is
// just for helm use case. Otherwise, include all values.
if cfg.ControlPlaneValues == "" {
for k, v := range cfg.Values {
cmd = append(cmd, "--set", fmt.Sprintf("values.%s=%s", k, v))
}
}

scopes.CI.Infof("Running istioctl %v", cmd)
if _, err := istioCtl.Invoke(cmd); err != nil {
return nil, fmt.Errorf("manifest apply failed: %v", err)
}

if !cfg.SkipWaitForValidationWebhook {

// Wait for Galley & the validation webhook to come online before continuing
if _, _, err = env.WaitUntilServiceEndpointsAreReady(cfg.SystemNamespace, "istio-galley"); err != nil {
err = fmt.Errorf("error waiting %s/istio-galley service endpoints: %v", cfg.SystemNamespace, err)
scopes.CI.Info(err.Error())
i.Dump()
return nil, err
}

// Wait for webhook to come online. The only reliable way to do that is to see if we can submit invalid config.
err = waitForValidationWebhook(env.Accessor)
if err != nil {
i.Dump()
return nil, err
}
}

return i, nil
}
4 changes: 0 additions & 4 deletions tests/integration/mixer/telemetry/logs/accesslog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"istio.io/istio/pkg/test/framework/components/galley"
"istio.io/istio/pkg/test/framework/components/ingress"
"istio.io/istio/pkg/test/framework/components/istio"
"istio.io/istio/pkg/test/framework/components/mixer"
"istio.io/istio/pkg/test/framework/components/namespace"
"istio.io/istio/pkg/test/framework/resource"
util "istio.io/istio/tests/integration/mixer"
Expand Down Expand Up @@ -94,9 +93,6 @@ func testsetup(ctx resource.Context) error {
return err
}
galInst = &g
if _, err = mixer.New(ctx, mixer.Config{Galley: g}); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this factored in with the operator already ?
Or was this just validating ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not doing anything really except port forwarding to mixer then doing nothing. It's not actually installing mixer. I forget if I made this change to fix anything or if I was cleaning this up, I have been working on this off and on for a couple months

return err
}
ing, err := ingress.New(ctx, ingress.Config{Istio: ist})
if err != nil {
return err
Expand Down
8 changes: 8 additions & 0 deletions tests/integration/pilot/mcp/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,12 @@ func setupConfig(cfg *istio.Config) {
}
cfg.Values["galley.enableServiceDiscovery"] = "true"
cfg.Values["pilot.configSource.subscribedResources[0]"] = "SERVICE_REGISTRY"
// ICP doesn't support set with list, so need to override here
cfg.ControlPlaneValues = `
galley:
enableServiceDiscovery: true
pilot:
configSource:
subscribedResources: ["SERVICE_REGISTRY"
`
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package sds_ingress
package sdsingress

import (
"testing"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package sds_ingress
package sdsingress

import (
"testing"
Expand All @@ -21,7 +21,7 @@ import (
"istio.io/istio/pkg/test/framework"
"istio.io/istio/pkg/test/framework/components/environment"
"istio.io/istio/pkg/test/framework/components/ingress"
ingressutil "istio.io/istio/tests/integration/security/sds_ingress/util"
ingressutil "istio.io/istio/tests/integration/security/sdsingress/util"
)

// TestMultiMtlsGateway_InvalidSecret tests a single mTLS ingress gateway with SDS enabled. Creates kubernetes secret
Expand Down
Loading