ronantakizawa/codereview-bench huggingface dataset:
Repository: ionic-team/ionic-framework
File: core/src/components/textarea/test/rows/textarea.e2e.ts (TypeScript)

Code before:
            rows="3"
            size="small"
            label="Small Size"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <h2>Rows: 3, Size Medium</h2>
          <ion-textarea
            rows="3"
            size="medium"
            label="Medium Size"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <h2>Rows: 3, Size Large</h2>
          <ion-textarea
            rows="3"
            size="large"
            label="Large Size"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

      const container = page.locator('#container');
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows-different-sizes`));
    });

    test('should respect rows when auto-grow is enabled', async ({ page }) => {
      await page.setContent(
        `
        <div id="container" style="display: flex; flex-direction: column; gap: 20px;">
          <h2>Rows: 3, Auto-grow</h2>
          <ion-textarea
            rows="3"
            auto-grow="true"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

      const container = page.locator('#container');
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows-autogrow`));
    });
  });
});


Review comment (suggestion):
Let's be consistent with the standards of the file namings: 

```suggestion
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows-sizes`));
```

Code after:
          ></ion-textarea>
          <ion-textarea
            rows="3"
            size="medium"
            label="Medium Size"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <ion-textarea
            rows="3"
            size="large"
            label="Large Size"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

      const container = page.locator('#container');
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows-sizes`));
    });

    test('should respect rows when auto-grow is enabled', async ({ page }) => {
      await page.setContent(
        `
        <div id="container" style="display: flex; flex-direction: column; gap: 20px;">
          <ion-textarea
            rows="3"
            auto-grow="true"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

      const container = page.locator('#container');
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows-autogrow`));
    });
  });
});
Repository: ionic-team/ionic-framework
File: core/src/components/textarea/test/rows/textarea.e2e.ts (TypeScript)

Code before:
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

/**
 * This behavior does not vary across directions
 * This behavior only applies to the `ionic` theme.
 */
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
  test.describe(title('textarea: rows'), () => {
    test('should respect rows attribute with different values', async ({ page }) => {
      await page.setContent(
        `
        <div id="container" style="display: flex; flex-direction: column; gap: 20px;">
          <h2>Rows: 1</h2>
          <ion-textarea
            rows="1"
            label="Small"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <h2>Rows: 3</h2>
          <ion-textarea
            rows="3"
            label="Medium"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <h2>Rows: 8</h2>
          <ion-textarea
            rows="8"
            label="Large"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

Review comment (suggestion):
We don't need to explain that it has different values, it's pretty straight forward since the attribute is known to accept different values.

```suggestion
    test('should respect rows attribute', async ({ page }) => {
```

Code after:
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

/**
 * This behavior does not vary across directions
 * This behavior only applies to the `ionic` theme.
 */
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
  test.describe(title('textarea: rows'), () => {
    test('should respect rows attribute', async ({ page }) => {
      await page.setContent(
        `
        <div id="container" style="display: flex; flex-direction: column; gap: 20px;">
          <ion-textarea
            rows="1"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <ion-textarea
            rows="3"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <ion-textarea
            rows="8"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

      const container = page.locator('#container');
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows`));
Repository: ionic-team/ionic-framework
File: core/src/components/textarea/test/rows/textarea.e2e.ts (TypeScript)

Code before:
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

/**
 * This behavior does not vary across directions
 * This behavior only applies to the `ionic` theme.
 */
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
  test.describe(title('textarea: rows'), () => {
    test('should respect rows attribute with different values', async ({ page }) => {
      await page.setContent(
        `
        <div id="container" style="display: flex; flex-direction: column; gap: 20px;">
          <h2>Rows: 1</h2>
          <ion-textarea
            rows="1"
            label="Small"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <h2>Rows: 3</h2>
          <ion-textarea
            rows="3"
            label="Medium"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <h2>Rows: 8</h2>
          <ion-textarea
            rows="8"
            label="Large"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

      const container = page.locator('#container');
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows-different-values`));
    });

Review comment (suggestion):
Remove the headers. When it comes to snapshots, we want it to be as bare as possible in order for the snapshots to be as small as possible. Remove the headers for the rest of the file too.

Code after:
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

/**
 * This behavior does not vary across directions
 * This behavior only applies to the `ionic` theme.
 */
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
  test.describe(title('textarea: rows'), () => {
    test('should respect rows attribute', async ({ page }) => {
      await page.setContent(
        `
        <div id="container" style="display: flex; flex-direction: column; gap: 20px;">
          <ion-textarea
            rows="1"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <ion-textarea
            rows="3"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
          <ion-textarea
            rows="8"
            label="Comments"
            value="1&#10;2&#10;3&#10;4&#10;5&#10;6&#10;7&#10;8&#10;9&#10;0"
          ></ion-textarea>
        </div>
      `,
        config
      );

      const container = page.locator('#container');
      await expect(container).toHaveScreenshot(screenshot(`textarea-rows`));
    });

    test('should respect rows attribute with different sizes', async ({ page }) => {
      await page.setContent(
Repository: istio/istio
File: tests/integration/telemetry/api/setup_test.go (Go)

Code before:
	for _, c := range ctx.Clusters() {
		ingr = append(ingr, ist.IngressFor(c))
	}
	mockProm = match.ServiceName(echo.NamespacedName{Name: "mock-prom", Namespace: apps.Namespace}).GetMatches(apps.Echos().All.Instances())
	promInst, err = prometheus.New(ctx, prometheus.Config{})
	if err != nil {
		return
	}

	args := map[string]any{
		"DockerConfigJson": base64.StdEncoding.EncodeToString(
			[]byte(createDockerCredential(registryUser, registryPasswd, registry.Address()))),
	}
	if err := ctx.ConfigIstio().EvalFile(apps.Namespace.Name(), args, "testdata/registry-secret.yaml").
		Apply(apply.CleanupConditionally); err != nil {
		return err
	}
	return nil
}

// The function validates if the cluster is a "Kind" cluster,
// By looking into a context name. Expects "kind-" prefix.
// That is required by some tests for specific actions on "Kind".
func IsKindCluster() (bool, error) {
	config, err := clientcmd.LoadFromFile(clientcmd.RecommendedHomeFile)
	if err != nil {
		return false, err
	}
	currentContext := config.CurrentContext
	return currentContext == "kind-kind" || len(currentContext) > 5 && currentContext[:5] == "kind-", nil
}


Review comment (suggestion):
Hmm, thinking about this more -- this is looking at the current context pointed at, but that isn't always how the test is configured. For multiclsuter, for instance, ` --istio.test.kube.topology=opology-config.json` is used to point to a set of clusters that are unrelated to the current context.

The most reliable way would be to somehow get this from `(resource.Context).Clusters()`. I don't know how to get from there to the info we need, though.

Code after:

	for _, c := range ctx.Clusters() {
		ingr = append(ingr, ist.IngressFor(c))
	}
	mockProm = match.ServiceName(echo.NamespacedName{Name: "mock-prom", Namespace: apps.Namespace}).GetMatches(apps.Echos().All.Instances())
	promInst, err = prometheus.New(ctx, prometheus.Config{})
	if err != nil {
		return
	}

	args := map[string]any{
		"DockerConfigJson": base64.StdEncoding.EncodeToString(
			[]byte(createDockerCredential(registryUser, registryPasswd, registry.Address()))),
	}
	if err := ctx.ConfigIstio().EvalFile(apps.Namespace.Name(), args, "testdata/registry-secret.yaml").
		Apply(apply.CleanupConditionally); err != nil {
		return err
	}
	return nil
}

// The function validates if the cluster is a "Kind" cluster,
// By looking into a context name. Expects "kind-" prefix.
// That is required by some tests for specific actions on "Kind".
func IsKindCluster() (bool, error) {
	kubeconfig := os.Getenv("KUBECONFIG")
	if kubeconfig == "" {
		kubeconfig = clientcmd.RecommendedHomeFile
	}

	config, err := clientcmd.LoadFromFile(kubeconfig)
	if err != nil {
		if os.IsNotExist(err) {
			return false, fmt.Errorf("kubeconfig file not found: %s", kubeconfig)
		}
		return false, err
	}
	currentContext := config.CurrentContext
	return currentContext == "kind-kind" || len(currentContext) > 5 && currentContext[:5] == "kind-", nil
}
Repository: istio/istio
File: tests/integration/ambient/waypoint_test.go (Go)

Code before:
				ingress.CallOrFail(t, echo.CallOptions{
					Port: echo.Port{
						Protocol:    protocol.HTTP,
						ServicePort: 80,
					},
					Scheme: scheme.HTTP,
					Check:  CheckDeny,
				})
			})
			t.NewSubTest("service routing").Run(func(t framework.TestContext) {
				// This will be ignored entirely if there is only workload waypoint, so this behaves the same as endpoint routing.
				SetIngressUseWaypoint(t, apps.WorkloadAddressedWaypoint.ServiceName(), apps.WorkloadAddressedWaypoint.NamespaceName())
				ingress.CallOrFail(t, echo.CallOptions{
					Port: echo.Port{
						Protocol:    protocol.HTTP,
						ServicePort: 80,
					},
					Scheme: scheme.HTTP,
					Check:  CheckDeny,
				})
			})
		})
	})
}

func SetIngressUseWaypoint(t framework.TestContext, name, ns string) {
	for _, c := range t.Clusters() {
		set := func(service bool) error {
			var set string
			if service {
				set = fmt.Sprintf("%q", "true")
			} else {
				set = "null"
			}
			label := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":%s}}}`,
				"istio.io/ingress-use-waypoint", set))
			_, err := c.Kube().CoreV1().Services(ns).Patch(context.TODO(), name, types.MergePatchType, label, metav1.PatchOptions{})
			return err
		}

		if err := set(true); err != nil {
			t.Fatal(err)
		}
		t.Cleanup(func() {
			if err := set(false); err != nil {
				scopes.Framework.Errorf("failed resetting service-addressed for %s", name)
			}
		})
	}
}


Review comment (suggestion):
We may need to add a comment:
Running `TestTCPRoute` and `TestTLSRoute` needs to set `PILOT_ENABLE_ALPHA_GATEWAY_API` to `true` since that are still under alpha Gateway API.

Code after:
				ingress.CallOrFail(t, echo.CallOptions{
					Port: echo.Port{
						Protocol:    protocol.HTTP,
						ServicePort: 80,
					},
					Scheme: scheme.HTTP,
					Check:  CheckDeny,
				})
			})
			t.NewSubTest("service routing").Run(func(t framework.TestContext) {
				// This will be ignored entirely if there is only workload waypoint, so this behaves the same as endpoint routing.
				SetIngressUseWaypoint(t, apps.WorkloadAddressedWaypoint.ServiceName(), apps.WorkloadAddressedWaypoint.NamespaceName())
				ingress.CallOrFail(t, echo.CallOptions{
					Port: echo.Port{
						Protocol:    protocol.HTTP,
						ServicePort: 80,
					},
					Scheme: scheme.HTTP,
					Check:  CheckDeny,
				})
			})
		})
	})
}

func TestTCPRoute(t *testing.T) {
	framework.NewTest(t).Run(func(t framework.TestContext) {
		t.ConfigIstio().YAML(apps.Namespace.Name(), `apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: tcproute
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: service-addressed-waypoint
  rules:
    - backendRefs:
        - name: captured
          port: 9090
          weight: 3
        - name: uncaptured
          port: 9090
          weight: 1
        - name: service-addressed-waypoint
          port: 9093
          weight: 1
`).ApplyOrFail(t)
		apps.Captured[0].CallOrFail(t, echo.CallOptions{
			To:    apps.ServiceAddressedWaypoint,
			Port:  ports.TCP,
Repository: istio/istio
File: pilot/pkg/bootstrap/istio_ca.go (Go)

Code before:
	})
	return raServer, err
}

// checkCABundleCompleteness checks if all required CA certificate files exist
func checkCABundleCompleteness(
	signingKeyFile, signingCertFile, rootCertFile string,
	chainFiles []string,
) (
	signingCABundleComplete bool,
	bundleExists bool,
	err error,
) {
	signingKeyExists, err := fileExists(signingKeyFile)
	if err != nil {
		return false, false, err
	}

	signingCertExists, err := fileExists(signingCertFile)
	if err != nil {
		return false, signingKeyExists, err
	}

	rootCertExists, err := fileExists(rootCertFile)
	if err != nil {
		return false, signingKeyExists || signingCertExists, err
	}

	chainFilesExist, err := hasValidChainFiles(chainFiles)
	if err != nil {
		return false, signingKeyExists || signingCertExists || rootCertExists, err
	}

	bundleExists = signingKeyExists || signingCertExists || rootCertExists || chainFilesExist
	signingCABundleComplete = signingKeyExists && signingCertExists && rootCertExists && chainFilesExist

	return signingCABundleComplete, bundleExists, nil
}

// fileExists checks if a file exists and is accessible
func fileExists(filename string) (bool, error) {
	if filename == "" {
		return false, nil
	}
	_, err := os.Stat(filename)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, fmt.Errorf("error checking file %s: %v", filename, err)
	}

Review comment (suggestion):
The bundle might exist here but `checkCABundleCompleteness` will still return false. chainFilesExists might be `true`.

Code after:
	})
	return raServer, err
}

// checkCABundleCompleteness checks if all required CA certificate files exist
// this function may return bundleExists as false even when some files exist in case of an error
func checkCABundleCompleteness(
	signingKeyFile, signingCertFile, rootCertFile string,
	chainFiles []string,
) (
	signingCABundleComplete bool,
	bundleExists bool,
	err error,
) {
	signingKeyExists, err := fileExists(signingKeyFile)
	if err != nil {
		return false, false, err
	}

	signingCertExists, err := fileExists(signingCertFile)
	if err != nil {
		return false, signingKeyExists, err
	}

	rootCertExists, err := fileExists(rootCertFile)
	if err != nil {
		return false, signingKeyExists || signingCertExists, err
	}

	chainFilesExist, err := hasValidChainFiles(chainFiles)
	if err != nil {
		return false, signingKeyExists || signingCertExists || rootCertExists, err
	}

	bundleExists = signingKeyExists || signingCertExists || rootCertExists || chainFilesExist
	signingCABundleComplete = signingKeyExists && signingCertExists && rootCertExists && chainFilesExist

	return signingCABundleComplete, bundleExists, nil
}

// fileExists checks if a file exists and is accessible
func fileExists(filename string) (bool, error) {
	if filename == "" {
		return false, nil
	}
	_, err := os.Stat(filename)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, fmt.Errorf("error checking file %s: %v", filename, err)
Repository: istio/istio
File: istioctl/pkg/writer/pilot/status.go (Go)

Code before:

	if w != nil {
		if err := w.Flush(); err != nil {
			return fmt.Errorf("failed to flush tabwriter: %w", err)
		}
	}
	return nil
}

// getAllKnownXdsTypes returns a list of all known xDS type URLs, including core and extension types.
func getAllKnownXdsTypes() []string {
	// Core types
	types := []string{
		xdsresource.ClusterType,
		xdsresource.ListenerType,
		xdsresource.EndpointType,
		xdsresource.RouteType,
		xdsresource.ExtensionConfigurationType,
		// Add more known types here as needed
	}
	// In the future, this could be extended to include CRDs or dynamically discovered types
	return types
}

// joinWithTabs joins a string slice with tabs
func joinWithTabs(fields []string) string {
	return stringJoin(fields, "\t")
}

// stringJoin efficiently joins a string slice with a separator
func stringJoin(a []string, sep string) string {
	if len(a) == 0 {
		return ""
	}
	if len(a) == 1 {
		return a[0]
	}

	// Pre-allocate buffer with approximate size
	n := len(sep) * (len(a) - 1)
	for _, s := range a {
		n += len(s)
	}

	var b strings.Builder
	b.Grow(n)
	b.WriteString(a[0])
	for _, s := range a[1:] {
		b.WriteString(sep)
		b.WriteString(s)
	}

Review comment (performance):
What is the functional or performance benefit of implementing this manually? I think `strings.Join(fields, "\t")` already does what you want.

Code after:
		}
	}
	return nil
}

// getAllKnownXdsTypes returns a list of all known xDS type URLs, including core and extension types.
func getAllKnownXdsTypes() []string {
	// Core types
	types := []string{
		xdsresource.ClusterType,
		xdsresource.ListenerType,
		xdsresource.EndpointType,
		xdsresource.RouteType,
		xdsresource.ExtensionConfigurationType,
		// Add more known types here as needed
	}
	// In the future, this could be extended to include CRDs or dynamically discovered types
	return types
}

// setupStatusPrint processes the discovery responses and prepares them for printing
func (s *XdsStatusWriter) setupStatusPrint(drs map[string]*discovery.DiscoveryResponse) (*tabwriter.Writer, []*xdsWriterStatus, []string, error) {
	var fullStatus []*xdsWriterStatus
	allTypesSet := map[string]struct{}{}
	w := new(tabwriter.Writer).Init(s.Writer, 0, 8, 5, ' ', 0)

	// Process each discovery response
	for _, dr := range drs {
		for _, resource := range dr.Resources {
			clientConfig := xdsstatus.ClientConfig{}
			if err := resource.UnmarshalTo(&clientConfig); err != nil {
				return nil, nil, nil, fmt.Errorf("could not unmarshal ClientConfig: %w", err)
			}

			meta, err := model.ParseMetadata(clientConfig.GetNode().GetMetadata())
			if err != nil {
				return nil, nil, nil, fmt.Errorf("could not parse node metadata: %w", err)
			}

			// Skip if namespace filter is set and doesn't match
			if s.Namespace != "" && meta.Namespace != s.Namespace {
				continue
			}

			// Process XDS configs
			configs := handleAndGetXdsConfigs(&clientConfig)
			typeStatus := make(map[string]string, len(configs))
			for _, config := range configs {
				typeURL := config.GetTypeUrl()
				allTypesSet[typeURL] = struct{}{}
				typeStatus[typeURL] = formatStatus(config)
Repository: istio/istio
File: istioctl/pkg/admin/istiodconfig.go (Go)

Code before:
		})
	}
	err = rs.client.PutScopes(defaultScopes)
	if err != nil {
		return err
	}

	return nil
}

type levelState struct {
	client          *ControlzClient
	outputLogLevel  string
	stackTraceLevel string
}

func (ll *levelState) run(_ io.Writer) error {
	if ll.outputLogLevel != "" {
		scopeInfos, err := newScopeInfosFromScopeLevelPairs(ll.outputLogLevel)
		if err != nil {
			return err
		}
		err = ll.client.PutScopes(scopeInfos)
		if err != nil {
			return err
		}
	}
	if ll.stackTraceLevel != "" {
		scopeInfos, err := newScopeInfosFromScopeStackTraceLevelPairs(ll.stackTraceLevel)
		if err != nil {
			return err
		}
		err = ll.client.PutScopes(scopeInfos)
		if err != nil {
			return err
		}
	}
	return nil
}

type getAllLogLevelsState struct {
	client       *ControlzClient
	outputFormat string
}

func (ga *getAllLogLevelsState) run(out io.Writer) error {
	type scopeLogLevel struct {
		ScopeName       string `json:"scope_name"`
		LogLevel        string `json:"log_level"`
		StackTraceLevel string `json:"stack_trace_level"`
		Description     string `json:"description"`

Review comment (bug):
This is kinda a nit @my-git9, but I hope its not too hard to address. But the behavior is still a bit inconsistently if you specify both stack trace level and log level, but one of them fails. For example, if I run:

```bash
istioctl admin log --stack-trace-level wle:warn--level invalid-scope:warn
```

nothing will change, but if I do 

```bash
istioctl admin log --stack-trace-level invalid-scope:warn --level wle:warn
```

then, the log level will be updated, but the stack trace level wont.

Code after:
		})
	}
	err = rs.client.PutScopes(defaultScopes)
	if err != nil {
		return err
	}

	return nil
}

type levelState struct {
	client          *ControlzClient
	outputLogLevel  string
	stackTraceLevel string
}

func (ll *levelState) run(_ io.Writer) error {
	var scopeInfos []*ScopeInfo
	if ll.outputLogLevel != "" {
		scopeLogInfos, err := newScopeInfosFromScopeLevelPairs(ll.outputLogLevel)
		if err != nil {
			return err
		}
		scopeInfos = append(scopeInfos, scopeLogInfos...)
	}
	if ll.stackTraceLevel != "" {
		scopeStackInfos, err := newScopeInfosFromScopeStackTraceLevelPairs(ll.stackTraceLevel)
		if err != nil {
			return err
		}
		scopeInfos = append(scopeInfos, scopeStackInfos...)
	}
	err := ll.client.PutScopes(scopeInfos)
	if err != nil {
		return err
	}
	return nil
}

type getAllLogLevelsState struct {
	client       *ControlzClient
	outputFormat string
}

func (ga *getAllLogLevelsState) run(out io.Writer) error {
	type scopeLogLevel struct {
		ScopeName       string `json:"scope_name"`
		LogLevel        string `json:"log_level"`
		StackTraceLevel string `json:"stack_trace_level"`
		Description     string `json:"description"`
	}