Merge pull request #795 from openziti/release-next

Release 0.26.1
This commit is contained in:
Andrew
2022-07-14 19:05:48 -04:00
committed by GitHub
5 changed files with 305 additions and 155 deletions
+15 -8
View File
@@ -1,15 +1,16 @@
name: mattermost-ziti-webhook
on:
create:
delete:
on:
issues:
issue_comment:
pull_request_review:
types: [submitted]
pull_request_review_comment:
pull_request:
types: [opened, reopened]
push:
fork:
release:
types: [released]
workflow_dispatch:
jobs:
@@ -17,9 +18,15 @@ jobs:
runs-on: ubuntu-latest
name: POST Webhook
steps:
- uses: openziti/ziti-webhook-action@v2
if: github.repository_owner == 'openziti'
- uses: openziti/ziti-mattermost-action-py@main
if: |
github.repository_owner == 'openziti'
&& ((github.event_name != 'pull_request_review')
|| (github.event_name == 'pull_request_review' && github.event.review.state == 'approved'))
with:
ziti-id: ${{ secrets.ZITI_MATTERMOST_IDENTITY }}
webhook-url: ${{ secrets.ZITI_MATTERMOST_WEBHOOK_URL }}
webhook-secret: ${{ secrets.ZITI_MATTERMOSTI_WEBHOOK_SECRET }}
zitiId: ${{ secrets.ZITI_MATTERMOST_IDENTITY }}
webhookUrl: ${{ secrets.ZHOOK_URL }}
eventJson: ${{ toJson(github.event) }}
senderUsername: "GitHubZ"
destChannel: "dev-notifications"
+24
View File
@@ -1,3 +1,27 @@
# Release 0.26.1
There was a missed dependency update for xweb in 0.26.0 that kept SNI from working in HTTP API components. This would
affect SNI support for all REST APIs.
## What's New
- Edge
- Fixes missing identity update in xweb
- Fabric
- Fixes missing identity update in xweb
- Bug Fixes
- Ziti CLI
- N/A
- SDK Golang
- N/A
## Edge
### Bug Fixes
* (Fix panic on remote resolve connections)[https://github.com/openziti/edge/pull/1088]
## Fabric
### Bug Fixes
* (Logging erroneously indicates conflicting conditions returned from route attempt)[https://github.com/openziti/fabric/issues/446]
# Release 0.26.0
## Breaking Changes
+7 -7
View File
@@ -23,16 +23,16 @@ require (
github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19
github.com/michaelquigley/pfxlog v0.6.9
github.com/openziti/agent v1.0.1
github.com/openziti/channel v0.18.52
github.com/openziti/edge v0.22.13
github.com/openziti/fabric v0.19.16
github.com/openziti/channel v0.18.53
github.com/openziti/edge v0.22.21
github.com/openziti/fabric v0.19.20
github.com/openziti/foundation/v2 v2.0.1
github.com/openziti/identity v1.0.4
github.com/openziti/identity v1.0.5
github.com/openziti/metrics v1.0.2
github.com/openziti/sdk-golang v0.16.97
github.com/openziti/sdk-golang v0.16.98
github.com/openziti/storage v0.1.14
github.com/openziti/transport/v2 v2.0.15
github.com/openziti/xweb/v2 v2.0.1
github.com/openziti/transport/v2 v2.0.16
github.com/openziti/xweb/v2 v2.0.2
github.com/openziti/ziti-db-explorer v1.1.1
github.com/pborman/uuid v1.2.0
github.com/pkg/errors v0.9.1
+14 -14
View File
@@ -667,32 +667,32 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openziti/agent v1.0.1 h1:mk3M6MOyK75Qc+lOdtKHywfaxnbSES9qi4NiLZQxOMU=
github.com/openziti/agent v1.0.1/go.mod h1:ALOg74f4b4GpUOjDPusp6lezbQa/7rgo09HOrodDWAw=
github.com/openziti/channel v0.18.52 h1:i7pst/JGQRtuTnve59Ra2i2MiJZL7M0k3wanqD5W9j8=
github.com/openziti/channel v0.18.52/go.mod h1:bjclQL6meYD5Uiw8xuKw0CI24gyzPTd7WW0IsfRk2/k=
github.com/openziti/channel v0.18.53 h1:YEGsizInlHoEPITJye/HZqTMykRvuzIoa4wrFMcSMkc=
github.com/openziti/channel v0.18.53/go.mod h1:6vF4dSujAqDsmJU5+g82pXvZRiagqq972E0uNA4LG9o=
github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k=
github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo=
github.com/openziti/edge v0.22.13 h1:5w6cMPd19rMFoDPhsF8PbLE4qLfMVM5WcfSE15FtMSA=
github.com/openziti/edge v0.22.13/go.mod h1:d0LCgwrz/YGvqwy+vf5Uv589bYo1ZZHEfmnkuOZ2JL0=
github.com/openziti/fabric v0.19.16 h1:KqxhVjVklyURJir+rC95GPeu0t2ZthSp6lX2ppV9Mfk=
github.com/openziti/fabric v0.19.16/go.mod h1:8AlLbXYyOR0PpEB+yW9cUDx4duys9YwvF4pcskj4LLA=
github.com/openziti/edge v0.22.21 h1:tPvj5CcdFGIEY6jSkM2dhbRht4n+X4J0ISa5qwgJ9Dg=
github.com/openziti/edge v0.22.21/go.mod h1:viW34MBUDZnLGW2mpHTnR89LHXYbmi74Umt2C6v6sNg=
github.com/openziti/fabric v0.19.20 h1:3hd6q2pCwGdGRySvoFAdBeyMQwMNHr5ZdIwsJLUzoDA=
github.com/openziti/fabric v0.19.20/go.mod h1:SLFSzdEqkCwJoW7nmUdeo2bvfDObK6M1h+fBQ8oUiGk=
github.com/openziti/foundation/v2 v2.0.1 h1:HKYwAyxlZ4zmlt0t9Y/v6SWso0qUaeWapkWOlQDKPEk=
github.com/openziti/foundation/v2 v2.0.1/go.mod h1:L75kwCC5WTUPqxuAd3G+WMBompaElMb/nYlJjR1sJ9Q=
github.com/openziti/identity v1.0.4 h1:48OuTuvJLTv32Vahonga+wHhS3GL8aFUgSHK2pqbcDs=
github.com/openziti/identity v1.0.4/go.mod h1:Nxf0CPFPkvdtFGvvsP4I/eZ//flU0q+sJVnLZDzlFOE=
github.com/openziti/identity v1.0.5 h1:PKW1tj0ctOWgscL3P4gKiVFfKrP6dYeP0U6R8Aw6DKM=
github.com/openziti/identity v1.0.5/go.mod h1:Nxf0CPFPkvdtFGvvsP4I/eZ//flU0q+sJVnLZDzlFOE=
github.com/openziti/jwks v1.0.1 h1:+BtBzDWFVUlJfCbBhQR0BZI3YNtoBvfhfdCUSSB0G+0=
github.com/openziti/jwks v1.0.1/go.mod h1:KwO0x9FBG0aoJS5f6nH5xeHoplyR1H143SMI9kF0mC8=
github.com/openziti/metrics v1.0.2 h1:X3ip93aDDgVeyhqxBLVwCtdG7/kILktFxcpl5N2+4+E=
github.com/openziti/metrics v1.0.2/go.mod h1:30EzUXm/VJfTVNoqPLx4x3mC/eslpCeh6wc4ejbZR/g=
github.com/openziti/sdk-golang v0.16.97 h1:FMdIQoSJl7iNrM0AhJMG8ChRZJ+2q1Y9jw6VzDuvPX4=
github.com/openziti/sdk-golang v0.16.97/go.mod h1:oHRuQCHv34DZG5XNHftBvjp5DR5tu6WtMnS52EHvWTQ=
github.com/openziti/sdk-golang v0.16.98 h1:djkdN8DHGuJehnGYTx5fD1gPqEhBy9v0rXj/eVXFtcc=
github.com/openziti/sdk-golang v0.16.98/go.mod h1:u/ft5kUJ2t4nxo0My33n0FNOc6MhBljmFJ4TpyfokEA=
github.com/openziti/storage v0.1.14 h1:JZv9OP0O4d3Z5c+ebaVpNUDJWrRsqgpTPHIwdCgYud0=
github.com/openziti/storage v0.1.14/go.mod h1:PXc1iYT8m+EmZf9EGyRTFwAToY1/jd5cAV2FFxL2D/g=
github.com/openziti/transport/v2 v2.0.15 h1:PsmNVsTeaav7/FHlczWlMhNW1wqdbVuC9ryAUzaywQw=
github.com/openziti/transport/v2 v2.0.15/go.mod h1:Dfd8ZORF/UHGrHL6FVaZka/58tFEKQK4tV0HSeqYBts=
github.com/openziti/transport/v2 v2.0.16 h1:dTo8TyJeYzLly04eadbN8o6m2tehzNNGadyL7abSMHk=
github.com/openziti/transport/v2 v2.0.16/go.mod h1:tkKEcr/NEjJ2NaYyn9ppAlXEidSOyusJGulfKLcqMws=
github.com/openziti/x509-claims v1.0.2 h1:PSv/xRfejIAcPc16A902k08rSBs3R8bjtL4qq6WEwCI=
github.com/openziti/x509-claims v1.0.2/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE=
github.com/openziti/xweb/v2 v2.0.1 h1:KF0bVCeiJ6TIJEsxdLZbnpdJKqZX095EiMTcoQynuz4=
github.com/openziti/xweb/v2 v2.0.1/go.mod h1:2+IpJFejJeJelA4QyAPluLS30hfyUP2eRTo9XD99W0Y=
github.com/openziti/xweb/v2 v2.0.2 h1:XYlVFriTq/U1wcUrc+XPnWJGhXh9NJPhtQ7+r3aC0cU=
github.com/openziti/xweb/v2 v2.0.2/go.mod h1:KQOOlnJk08EZT3TWkvDj/pbIUEVbgG0IrrNzl8gsi40=
github.com/openziti/ziti-db-explorer v1.1.1 h1:G0eoTby+aIjjt5TxEfR+FMI2CWd4RvZFjzaIMX2lEBw=
github.com/openziti/ziti-db-explorer v1.1.1/go.mod h1:h76h7Tsb+khb0v+CqYKL6ifUfJbUMjGBFU2IvupfBE4=
github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
+245 -126
View File
@@ -17,12 +17,14 @@
package edge
import (
"bytes"
"fmt"
"github.com/go-openapi/runtime"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/jedib0t/go-pretty/v6/text"
"github.com/openziti/foundation/v2/stringz"
"io"
"net/url"
"reflect"
"sort"
"strconv"
"strings"
@@ -30,7 +32,6 @@ import (
"github.com/Jeffail/gabs"
"github.com/openziti/edge/rest_management_api_client/certificate_authority"
"github.com/openziti/edge/rest_model"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/api"
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
@@ -291,7 +292,7 @@ func newSubListCmdForEntityType(entityType string, subType string, outputF outpu
Run: func(cmd *cobra.Command, args []string) {
options.Cmd = cmd
options.Args = args
err := runListChilden(entityType, subType, options, outputF)
err := runListChildren(entityType, subType, options, outputF)
cmdhelper.CheckErr(err)
},
SuggestFor: []string{},
@@ -339,20 +340,6 @@ func ListEntitiesOfType(entityType string, params url.Values, logJSON bool, out
return children, api.GetPaging(jsonParsed), err
}
func toInt64(c *gabs.Container, path string, errorHolder errorz.ErrorHolder) int64 {
data := c.S(path).Data()
if data == nil {
errorHolder.SetError(errors.Errorf("%v not found", path))
return 0
}
val, ok := data.(float64)
if !ok {
errorHolder.SetError(errors.Errorf("%v not a number, it's a %v", path, reflect.TypeOf(data)))
return 0
}
return int64(val)
}
// ListEntitiesOfType queries the Ziti Controller for entities of the given type
func filterSubEntitiesOfType(entityType, subType, entityId, filter string, o *api.Options) ([]*gabs.Container, *api.Paging, error) {
jsonParsed, err := util.EdgeControllerListSubEntities(entityType, subType, entityId, filter, o.OutputJSONResponse, o.Out, o.Timeout, o.Verbose)
@@ -802,87 +789,6 @@ func outputIdentities(o *api.Options, children []*gabs.Container, pagingInfo *ap
return nil
}
func outputPostureCheck(o *api.Options, entity *gabs.Container) error {
id, _ := entity.Path("id").Data().(string)
typeId, _ := entity.Path("typeId").Data().(string)
name, _ := entity.Path("name").Data().(string)
roleAttributes := entity.Path("roleAttributes").String()
config := ""
switch typeId {
case "MFA":
timeoutFloat, _ := entity.Path("timeoutSeconds").Data().(float64)
timeout := int64(timeoutFloat)
promptOnWake, _ := entity.Path("promptOnWake").Data().(bool)
promptOnUnlock, _ := entity.Path("promptOnUnlock").Data().(bool)
ignoreLegacyEndpoints, _ := entity.Path("ignoreLegacyEndpoints").Data().(bool)
config = fmt.Sprintf("timeout: %d, wake: %t, unlock: %t, ignore: %t", timeout, promptOnWake, promptOnUnlock, ignoreLegacyEndpoints)
case "MAC":
containers, _ := entity.Path("macAddresses").Children()
config = containerArrayToString(containers, 4)
case "DOMAIN":
containers, _ := entity.Path("domains").Children()
config = containerArrayToString(containers, 4)
case "OS":
operatingSystems, _ := entity.Path("operatingSystems").Children()
config = strings.Join(postureCheckOsToStrings(operatingSystems), ",")
case "PROCESS_MULTI":
postureCheck := rest_model.PostureCheckProcessMultiDetail{}
if err := postureCheck.UnmarshalJSON(entity.Bytes()); err != nil {
return err
}
baseConfig := fmt.Sprintf("(SEMANTIC: %s)", *postureCheck.Semantic)
if _, err := fmt.Fprintf(o.Out, "id: %-10v type: %-10v name: %-15v role attributes: %-10s param: %v\n", id, typeId, name, roleAttributes, baseConfig); err != nil {
return err
}
for _, process := range postureCheck.Processes {
process.SignerFingerprints = getEllipsesStrings(process.SignerFingerprints, 4, 2)
process.Hashes = getEllipsesStrings(process.Hashes, 4, 2)
_, _ = fmt.Fprintf(o.Out, "\t(OS: %s, PATH: %s, HASHES: %s, SIGNER: %s)\n", *process.OsType, *process.Path, strings.Join(process.Hashes, ","), strings.Join(process.SignerFingerprints, ", "))
}
return nil
case "PROCESS":
process := entity.Path("process")
os := process.Path("osType").Data().(string)
path := process.Path("path").Data().(string)
var hashStrings []string
if val := process.Path("hashes").Data(); val != nil {
hashes := val.([]interface{})
for _, hash := range hashes {
hashStr := hash.(string)
hashStrings = append(hashStrings, getEllipsesString(hashStr, 4, 2))
}
}
signerFingerprint := "N/A"
if val := process.Path("signerFingerprint").Data(); val != nil {
if valStr := val.(string); valStr != "" {
signerFingerprint = getEllipsesString(valStr, 4, 2)
}
}
if len(hashStrings) == 0 {
hashStrings = append(hashStrings, "N/A")
}
config = fmt.Sprintf("\n\t(OS: %s, PATH: %s, HASHES: %s, SIGNER: %s)", os, path, strings.Join(hashStrings, ","), signerFingerprint)
}
if _, err := fmt.Fprintf(o.Out, "id: %-10v type: %-10v name: %-15v role attributes: %-10s param: %v\n", id, typeId, name, roleAttributes, config); err != nil {
return err
}
return nil
}
func getEllipsesString(val string, lead, lag int) string {
total := lead + lag + 3
@@ -893,27 +799,254 @@ func getEllipsesString(val string, lead, lag int) string {
return val[0:lead] + "..." + val[len(val)-lag:]
}
func getEllipsesStrings(values []string, lead, lag int) []string {
var ret []string
for _, val := range values {
ret = append(ret, getEllipsesString(val, lead, lag))
func strSliceToStr(strs []string, width int) string {
builder := strings.Builder{}
for i, str := range strs {
if i != 0 {
if i%width == 0 {
builder.WriteRune('\n')
} else {
builder.WriteString(", ")
}
}
builder.WriteString(str)
}
return ret
return builder.String()
}
func outputPostureChecks(o *api.Options, children []*gabs.Container, pagingInfo *api.Paging) error {
if o.OutputJSONResponse {
func strSliceToStrEllipses(strs []string, width, lead, lag int) string {
var ret []string
for _, str := range strs {
ret = append(ret, getEllipsesString(str, lead, lag))
}
return strSliceToStr(ret, width)
}
func WrapHardEllipses(str string, wrapLen int) string {
newStr := text.WrapHard(str, wrapLen)
if newStr != str {
newStr = newStr[:len(newStr)-3] + "..."
}
return newStr
}
func outputPostureChecks(options *api.Options, children []*gabs.Container, pagingInfo *api.Paging) error {
if options.OutputJSONResponse {
return nil
}
for _, entity := range children {
if err := outputPostureCheck(o, entity); err != nil {
return err
outTable := table.NewWriter()
outTable.SetStyle(table.StyleRounded)
outTable.Style().Options.SeparateRows = true
rowConfigAutoMerge := table.RowConfig{AutoMerge: true}
outTable.AppendHeader(table.Row{"ID", "Name", "Type", "Attributes", "Configuration", "Configuration", "Configuration"}, rowConfigAutoMerge)
outTable.SetColumnConfigs([]table.ColumnConfig{
{Number: 1, AutoMerge: true},
{Number: 2, AutoMerge: true},
{Number: 3, AutoMerge: true, WidthMax: 20, WidthMaxEnforcer: WrapHardEllipses},
{Number: 4, AutoMerge: true, WidthMax: 20, WidthMaxEnforcer: WrapHardEllipses},
{Number: 5, WidthMax: 20, WidthMaxEnforcer: WrapHardEllipses},
{Number: 6, WidthMax: 50, WidthMaxEnforcer: WrapHardEllipses},
{Number: 7, WidthMax: 50, WidthMaxEnforcer: WrapHardEllipses},
})
for i, entity := range children {
json := entity.EncodeJSON()
detail, err := rest_model.UnmarshalPostureCheckDetail(bytes.NewBuffer(json), runtime.JSONConsumer())
id := stringz.OrEmpty(detail.ID())
name := stringz.OrEmpty(detail.Name())
timeout := "never"
roleAttributes := strSliceToStr(*detail.RoleAttributes(), 1)
if roleAttributes == "" {
roleAttributes = "<none>"
}
typeStr := detail.TypeID()
//defeat cell merging by adding a space every other row
if i%2 == 0 {
roleAttributes = roleAttributes + " "
typeStr = typeStr + " "
}
if err != nil {
msg := "Error unmarshalling index " + strconv.Itoa(i) + ": " + err.Error()
_, _ = options.ErrOutputWriter().Write([]byte(msg))
} else {
switch detail.TypeID() {
case "MFA":
mfaDetail := detail.(*rest_model.PostureCheckMfaDetail)
if mfaDetail.TimeoutSeconds > 0 {
timeout = fmt.Sprintf("%ds", mfaDetail.TimeoutSeconds)
}
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Timeout",
timeout,
timeout,
}, rowConfigAutoMerge)
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Prompt On Wake",
mfaDetail.PromptOnWake,
mfaDetail.PromptOnWake,
}, rowConfigAutoMerge)
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Prompt On Unlock",
mfaDetail.PromptOnUnlock,
mfaDetail.PromptOnUnlock,
}, rowConfigAutoMerge)
case "MAC":
macDetail := detail.(*rest_model.PostureCheckMacAddressDetail)
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"MAC Address",
strSliceToStrEllipses(macDetail.MacAddresses, 3, 3, 3),
strSliceToStrEllipses(macDetail.MacAddresses, 3, 3, 3),
}, rowConfigAutoMerge)
case "DOMAIN":
domainDetails := detail.(*rest_model.PostureCheckDomainDetail)
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Windows Domain",
strSliceToStr(domainDetails.Domains, 3),
strSliceToStr(domainDetails.Domains, 3),
}, rowConfigAutoMerge)
case "OS":
osDetails := detail.(*rest_model.PostureCheckOperatingSystemDetail)
for _, os := range osDetails.OperatingSystems {
osType := string(*os.Type)
for _, version := range os.Versions {
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
osType,
version,
version,
}, rowConfigAutoMerge)
}
}
case "PROCESS_MULTI":
procMultiDetail := detail.(*rest_model.PostureCheckProcessMultiDetail)
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Semantic",
string(*procMultiDetail.Semantic),
string(*procMultiDetail.Semantic),
}, rowConfigAutoMerge)
for _, process := range procMultiDetail.Processes {
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Path",
stringz.OrEmpty(process.Path),
stringz.OrEmpty(process.Path),
}, rowConfigAutoMerge)
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
" ",
"Hashes",
strSliceToStrEllipses(process.Hashes, 3, 4, 4),
})
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
" ",
"Signers",
strSliceToStrEllipses(process.SignerFingerprints, 1, 4, 4),
})
}
case "PROCESS":
procDetail := detail.(*rest_model.PostureCheckProcessDetail)
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Path",
stringz.OrEmpty(procDetail.Process.Path),
stringz.OrEmpty(procDetail.Process.Path),
}, rowConfigAutoMerge)
for _, hash := range procDetail.Process.Hashes {
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Hash",
getEllipsesString(hash, 4, 4),
getEllipsesString(hash, 4, 4),
}, rowConfigAutoMerge)
}
outTable.AppendRow(table.Row{
id,
name,
typeStr,
roleAttributes,
"Signer",
getEllipsesString(procDetail.Process.SignerFingerprint, 4, 4),
getEllipsesString(procDetail.Process.SignerFingerprint, 4, 4),
}, rowConfigAutoMerge)
}
}
}
pagingInfo.Output(o)
api.RenderTable(options, outTable, pagingInfo)
return nil
}
@@ -1183,7 +1316,7 @@ func runListRoleAttributes(entityType string, o *api.Options) error {
return nil
}
func runListChilden(parentType, childType string, o *api.Options, outputF outputFunction) error {
func runListChildren(parentType, childType string, o *api.Options, outputF outputFunction) error {
idOrName := o.Args[0]
parentId, err := mapNameToID(parentType, idOrName, *o)
if err != nil {
@@ -1257,20 +1390,6 @@ func runListSummary(o *api.Options) error {
return nil
}
func containerArrayToString(containers []*gabs.Container, limit int) string {
var values []string
for _, container := range containers {
value := container.Data().(string)
values = append(values, value)
}
valuesLength := len(values)
if valuesLength > limit {
values = values[:limit-1]
values = append(values, fmt.Sprintf(" and %d more", valuesLength-limit))
}
return strings.Join(values, ",")
}
func runListPostureCheckTypes(o *api.Options) error {
children, pagingInfo, err := listEntitiesWithOptions("posture-check-types", o)
@@ -1351,7 +1470,7 @@ func outputAuthPolicies(options *api.Options, children []*gabs.Container, info *
err := detail.UnmarshalJSON(json)
if err != nil {
msg := "Error unmarshaling index " + strconv.Itoa(i) + ": " + err.Error()
msg := "Error unmarshalling index " + strconv.Itoa(i) + ": " + err.Error()
_, _ = options.ErrOutputWriter().Write([]byte(msg))
} else {
secondarySigner := "<none>"