diff --git a/CHANGELOG.md b/CHANGELOG.md index 55ae404c0a..41cd142fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## v2.10.0 / 2023-08-31 + +### Note +- Label and annotation metrics aren't exposed by default anymore to reduce the memory usage of the default configuration of kube-state-metrics. Before this change, they used to only include the name and namespace of the objects which is not relevant to users not opting in these metrics. + +* [BUGFIX] Log no _info suffix in name only once per reading the configuration for custommetrics by @chrischdi in https://github.com/kubernetes/kube-state-metrics/pull/2157 +* [BUGFIX] Don't crash on non-existent valueFrom path values by @chihshenghuang in https://github.com/kubernetes/kube-state-metrics/pull/2140 +* [BUGFIX] Index out of range in metrics_store.SanitizeHeaders by @mrueg in https://github.com/kubernetes/kube-state-metrics/pull/2166 +* [BUGFIX] Always extract the headers but only write it when we have custommetrics by @chrischdi in https://github.com/kubernetes/kube-state-metrics/pull/2154 +* [BUGFIX] Add filtering for Lease metrics by @ntoofu in https://github.com/kubernetes/kube-state-metrics/pull/2122 +* [FEATURE] Implement kube_pod_status_initialized_time by @opeco17 in https://github.com/kubernetes/kube-state-metrics/pull/2148 +* [FEATURE] Disable labels and annotations metrics when metric-annotations-… by @opeco17 in https://github.com/kubernetes/kube-state-metrics/pull/2145 +* [FEATURE] Add webhooks client config service metrics by @dgrisonnet in https://github.com/kubernetes/kube-state-metrics/pull/2114 +* [FEATURE] Support kube_persistentvolumeclaim_deletion_timestamp by @maxime1907 in https://github.com/kubernetes/kube-state-metrics/pull/2074 +* [FEATURE] Support kube_persistentvolume_deletion_timestamp by @maxime1907 in https://github.com/kubernetes/kube-state-metrics/pull/2075 +* [FEATURE] Adds new metric `kube_pod_service_account` by @swarup-stripe in https://github.com/kubernetes/kube-state-metrics/pull/2096 +* [FEATURE] Add volumemode to PVC info metric by @machadovilaca in https://github.com/kubernetes/kube-state-metrics/pull/2134 +* [FEATURE] Enable metric-annotations-allowlist and metric-labels-allowlist for ResourceQuota by @opeco17 in https://github.com/kubernetes/kube-state-metrics/pull/2175 +* [FEATURE] Allow field KV general matching by @rexagod in https://github.com/kubernetes/kube-state-metrics/pull/2067 +* [FEATURE] Support hot reload for kubeconfig by @opeco17 in https://github.com/kubernetes/kube-state-metrics/pull/2144 +* [FEATURE] Add support for endpoint topology routing hints by @MarkSRobinson in https://github.com/kubernetes/kube-state-metrics/pull/2090 + ## v2.9.2 / 2023-05-30 This release does not incorporate any user-facing changes. Re-running release procedures as the process for the previous release failed. Changes are listed in v2.9.0. diff --git a/README.md b/README.md index abd9df5e6b..54ddc6b9e9 100644 --- a/README.md +++ b/README.md @@ -73,11 +73,11 @@ Generally, it is recommended to use the latest release of kube-state-metrics. If | kube-state-metrics | Kubernetes client-go Version | |--------------------|:----------------------------:| -| **v2.5.0** | v1.24 | | **v2.6.0** | v1.24 | | **v2.7.0** | v1.25 | | **v2.8.2** | v1.26 | | **v2.9.2** | v1.26 | +| **v2.10.0** | v1.27 | | **main** | v1.27 | @@ -90,8 +90,8 @@ release. #### Container Image The latest container image can be found at: -* `registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.9.2` (arch: `amd64`, `arm`, `arm64`, `ppc64le` and `s390x`) -* View all multi-architecture images at [here](https://explore.ggcr.dev/?image=registry.k8s.io%2Fkube-state-metrics%2Fkube-state-metrics:v2.9.2) +* `registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.0` (arch: `amd64`, `arm`, `arm64`, `ppc64le` and `s390x`) +* View all multi-architecture images at [here](https://explore.ggcr.dev/?image=registry.k8s.io%2Fkube-state-metrics%2Fkube-state-metrics:v2.10.0) ### Metrics Documentation diff --git a/VERSION b/VERSION index 5d9ade10c6..10c2c0c3d6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.9.2 +2.10.0 diff --git a/docs/endpointslice-metrics.md b/docs/endpointslice-metrics.md index 59af50bda4..9b914e3544 100644 --- a/docs/endpointslice-metrics.md +++ b/docs/endpointslice-metrics.md @@ -6,5 +6,6 @@ | kube_endpointslice_info | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace> | EXPERIMENTAL | | kube_endpointslice_ports | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`port_name`=<endpointslice-port-name>
`port_protocol`=<endpointslice-port-protocol>
`port_number`=<endpointslice-port-number> | EXPERIMENTAL | | kube_endpointslice_endpoints | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`ready`=<endpointslice-ready>
`serving`=<endpointslice-serving>
`terminating`=<endpointslice-terminating>
`hostname`=<endpointslice-hostname>
`targetref_kind`=<endpointslice-targetref-kind>
`targetref_name`=<endpointslice-targetref-name>
`targetref_namespace`=<endpointslice-targetref-namespace>
`nodename`=<endpointslice-nodename>
`endpoint_zone`=<endpointslice-zone> | EXPERIMENTAL | +| kube_endpointslice_endpoints_hints | Gauge | Each line is a hint applied to an endpoint-slice | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`address`=<endpointslice-address[0]>
`for_zone`=<endpointslice-hint> | EXPERIMENTAL | | kube_endpointslice_labels | Gauge | Kubernetes labels converted to Prometheus labels controlled via [--metric-labels-allowlist](./cli-arguments.md) | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace>
`label_ENDPOINTSLICE_LABEL`=<ENDPOINTSLICE_LABEL> | EXPERIMENTAL | | kube_endpointslice_created | Gauge | | `endpointslice`=<endpointslice-name>
`namespace`=<endpointslice-namespace> | EXPERIMENTAL | diff --git a/examples/autosharding/cluster-role-binding.yaml b/examples/autosharding/cluster-role-binding.yaml index 4ccf138483..ac698e55b6 100644 --- a/examples/autosharding/cluster-role-binding.yaml +++ b/examples/autosharding/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/autosharding/cluster-role.yaml b/examples/autosharding/cluster-role.yaml index c94145f587..3171418165 100644 --- a/examples/autosharding/cluster-role.yaml +++ b/examples/autosharding/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/autosharding/role-binding.yaml b/examples/autosharding/role-binding.yaml index 774fab191c..252f59598c 100644 --- a/examples/autosharding/role-binding.yaml +++ b/examples/autosharding/role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system roleRef: diff --git a/examples/autosharding/role.yaml b/examples/autosharding/role.yaml index a0c9dea719..e4562c3732 100644 --- a/examples/autosharding/role.yaml +++ b/examples/autosharding/role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system rules: diff --git a/examples/autosharding/service-account.yaml b/examples/autosharding/service-account.yaml index 76dfe2511f..fa83a8e6e0 100644 --- a/examples/autosharding/service-account.yaml +++ b/examples/autosharding/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/autosharding/service.yaml b/examples/autosharding/service.yaml index f9ed7f8a7a..19aca0a936 100644 --- a/examples/autosharding/service.yaml +++ b/examples/autosharding/service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system spec: diff --git a/examples/autosharding/statefulset.yaml b/examples/autosharding/statefulset.yaml index e0e21ad2c0..4cebb09b61 100644 --- a/examples/autosharding/statefulset.yaml +++ b/examples/autosharding/statefulset.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system spec: @@ -18,7 +18,7 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 spec: automountServiceAccountToken: true containers: @@ -34,7 +34,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.9.2 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.0 livenessProbe: httpGet: path: /healthz diff --git a/examples/daemonsetsharding/cluster-role-binding.yaml b/examples/daemonsetsharding/cluster-role-binding.yaml index 4ccf138483..ac698e55b6 100644 --- a/examples/daemonsetsharding/cluster-role-binding.yaml +++ b/examples/daemonsetsharding/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/daemonsetsharding/cluster-role.yaml b/examples/daemonsetsharding/cluster-role.yaml index c94145f587..3171418165 100644 --- a/examples/daemonsetsharding/cluster-role.yaml +++ b/examples/daemonsetsharding/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/daemonsetsharding/daemonset-service.yaml b/examples/daemonsetsharding/daemonset-service.yaml index 6d444b3e2d..739889210a 100644 --- a/examples/daemonsetsharding/daemonset-service.yaml +++ b/examples/daemonsetsharding/daemonset-service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics-shard - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics-shard namespace: kube-system spec: diff --git a/examples/daemonsetsharding/daemonset.yaml b/examples/daemonsetsharding/daemonset.yaml index f76067fe2a..3ae83cf6c4 100644 --- a/examples/daemonsetsharding/daemonset.yaml +++ b/examples/daemonsetsharding/daemonset.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics-shard - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics-shard namespace: kube-system spec: @@ -16,7 +16,7 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics-shard - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 spec: automountServiceAccountToken: true containers: @@ -29,7 +29,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.9.2 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.0 livenessProbe: httpGet: path: /healthz diff --git a/examples/daemonsetsharding/deployment-service.yaml b/examples/daemonsetsharding/deployment-service.yaml index f9ed7f8a7a..19aca0a936 100644 --- a/examples/daemonsetsharding/deployment-service.yaml +++ b/examples/daemonsetsharding/deployment-service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system spec: diff --git a/examples/daemonsetsharding/deployment.yaml b/examples/daemonsetsharding/deployment.yaml index 4d2e671852..57a43aaa91 100644 --- a/examples/daemonsetsharding/deployment.yaml +++ b/examples/daemonsetsharding/deployment.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system spec: @@ -17,13 +17,13 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 spec: automountServiceAccountToken: true containers: - args: - --resources=certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,leases,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.9.2 + image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.0 livenessProbe: httpGet: path: /healthz diff --git a/examples/daemonsetsharding/service-account.yaml b/examples/daemonsetsharding/service-account.yaml index 76dfe2511f..fa83a8e6e0 100644 --- a/examples/daemonsetsharding/service-account.yaml +++ b/examples/daemonsetsharding/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/standard/cluster-role-binding.yaml b/examples/standard/cluster-role-binding.yaml index 4ccf138483..ac698e55b6 100644 --- a/examples/standard/cluster-role-binding.yaml +++ b/examples/standard/cluster-role-binding.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/examples/standard/cluster-role.yaml b/examples/standard/cluster-role.yaml index c94145f587..3171418165 100644 --- a/examples/standard/cluster-role.yaml +++ b/examples/standard/cluster-role.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics rules: - apiGroups: diff --git a/examples/standard/deployment.yaml b/examples/standard/deployment.yaml index 31e37f7af1..471275b152 100644 --- a/examples/standard/deployment.yaml +++ b/examples/standard/deployment.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system spec: @@ -17,11 +17,11 @@ spec: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 spec: automountServiceAccountToken: true containers: - - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.9.2 + - image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.0 livenessProbe: httpGet: path: /healthz diff --git a/examples/standard/service-account.yaml b/examples/standard/service-account.yaml index 76dfe2511f..fa83a8e6e0 100644 --- a/examples/standard/service-account.yaml +++ b/examples/standard/service-account.yaml @@ -5,6 +5,6 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system diff --git a/examples/standard/service.yaml b/examples/standard/service.yaml index f9ed7f8a7a..19aca0a936 100644 --- a/examples/standard/service.yaml +++ b/examples/standard/service.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/version: 2.9.2 + app.kubernetes.io/version: 2.10.0 name: kube-state-metrics namespace: kube-system spec: diff --git a/internal/store/endpointslice.go b/internal/store/endpointslice.go index ad72ce794a..bf80cebbd4 100644 --- a/internal/store/endpointslice.go +++ b/internal/store/endpointslice.go @@ -74,6 +74,44 @@ func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string) } }), ), + *generator.NewFamilyGeneratorWithStability( + "kube_endpointslice_endpoints_hints", + "Topology routing hints attached to endpoints", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapEndpointSliceFunc(func(e *discoveryv1.EndpointSlice) *metric.Family { + m := []*metric.Metric{} + for _, ep := range e.Endpoints { + // Hint is populated when the endpoint is configured to be zone aware and preferentially route requests to its local zone. + // If there is no hint, skip this metric + if ep.Hints != nil && len(ep.Hints.ForZones) > 0 { + var ( + labelKeys, + labelValues []string + ) + + // Per Docs. + // This must contain at least one address but no more than + // 100. These are all assumed to be fungible and clients may choose to only + // use the first element. Refer to: https://issue.k8s.io/106267 + labelKeys = append(labelKeys, "address") + labelValues = append(labelValues, ep.Addresses[0]) + + for _, zone := range ep.Hints.ForZones { + m = append(m, &metric.Metric{ + LabelKeys: append(labelKeys, "for_zone"), + LabelValues: append(labelValues, zone.Name), + Value: 1, + }) + } + } + } + return &metric.Family{ + Metrics: m, + } + }), + ), *generator.NewFamilyGeneratorWithStability( "kube_endpointslice_endpoints", "Endpoints attached to the endpointslice.", @@ -134,9 +172,11 @@ func endpointSliceMetricFamilies(allowAnnotationsList, allowLabelsList []string) for _, address := range ep.Addresses { newlabelValues := make([]string, len(labelValues)) copy(newlabelValues, labelValues) + newlabelValues = append(newlabelValues, address) + m = append(m, &metric.Metric{ LabelKeys: labelKeys, - LabelValues: append(newlabelValues, address), + LabelValues: newlabelValues, Value: 1, }) } diff --git a/internal/store/endpointslice_test.go b/internal/store/endpointslice_test.go index 549fa73b6f..16a6ff61d8 100644 --- a/internal/store/endpointslice_test.go +++ b/internal/store/endpointslice_test.go @@ -113,7 +113,9 @@ func TestEndpointSliceStore(t *testing.T) { }, Want: ` # HELP kube_endpointslice_endpoints Endpoints attached to the endpointslice. + # HELP kube_endpointslice_endpoints_hints Topology routing hints attached to endpoints # TYPE kube_endpointslice_endpoints gauge + # TYPE kube_endpointslice_endpoints_hints gauge kube_endpointslice_endpoints{address="10.0.0.1",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1 kube_endpointslice_endpoints{address="192.168.1.10",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1 `, @@ -122,6 +124,44 @@ func TestEndpointSliceStore(t *testing.T) { "kube_endpointslice_endpoints", }, }, + { + Obj: &discoveryv1.EndpointSlice{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test_endpointslice-endpoints", + }, + AddressType: "IPv4", + Endpoints: []discoveryv1.Endpoint{ + { + NodeName: &nodename, + Conditions: discoveryv1.EndpointConditions{ + Ready: &ready, + Terminating: &terminating, + }, + Hostname: &hostname, + Zone: &zone, + Addresses: addresses, + Hints: &discoveryv1.EndpointHints{ + ForZones: []discoveryv1.ForZone{ + {Name: "zone1"}, + }, + }, + }, + }, + }, + Want: ` + # HELP kube_endpointslice_endpoints Endpoints attached to the endpointslice. + # HELP kube_endpointslice_endpoints_hints Topology routing hints attached to endpoints + # TYPE kube_endpointslice_endpoints gauge + # TYPE kube_endpointslice_endpoints_hints gauge + kube_endpointslice_endpoints_hints{address="10.0.0.1",endpointslice="test_endpointslice-endpoints",for_zone="zone1"} 1 + kube_endpointslice_endpoints{address="10.0.0.1",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1 + kube_endpointslice_endpoints{address="192.168.1.10",endpoint_nodename="node",endpoint_zone="west",endpointslice="test_endpointslice-endpoints",hostname="host",ready="true",terminating="false"} 1 + `, + + MetricNames: []string{ + "kube_endpointslice_endpoints", + }, + }, { AllowAnnotationsList: []string{ "foo",