diff --git a/apps/models.go b/apps/models.go deleted file mode 100644 index 44c17c2..0000000 --- a/apps/models.go +++ /dev/null @@ -1,1104 +0,0 @@ -package apps - -import ( - "encoding/json" - "time" -) - -type Error struct { - Code string - Message string - Status int64 -} - -type ErrorResponse struct { - Error *Error -} - -type AppType string - -const ( - AppTypeSystem AppType = "system" - AppTypeInternal AppType = "internal" - AppTypeCustom AppType = "custom" -) - -var AppCapabilityValues = map[string]int32{ - "UNSPECIFIED_APP_CAPABILITY": 0, - "permitPropagation": 1, - "permitIngestion": 2, - "rightPropagation": 3, - "rightIngestion": 4, - "tagOrchestration": 5, -} - -var AppContactTypeValues = map[string]int32{ - "UNSPECIFIED_APP_CONTACT_TYPE": 0, - "technical": 1, - "marketing": 2, - "finance": 3, - "security": 4, -} - -var AppMarketplaceCategoryValues = map[string]int32{ - "UNSPECIFIED_APP_MARKETPLACE_CATEGORY": 0, - "privacy": 1, - "asset": 2, -} - -var AppTypeValues = map[AppType]int32{ - "UnspecifiedAppType": 0, - "SystemAppType": 1, - "InternalAppType": 2, - "CustomAppType": 3, -} - -var AppAllowedInstancesValues = map[string]int32{ - "UnspecifiedAppAllowedInstances": 0, - "MultipleAppAllowedInstances": 1, - "SingleAppAllowedInstances": 2, -} - -var DataRoleValues = map[string]int32{ - "DATA_ROLE_UNSPECIFIED": 0, - "processor": 1, - "controller": 2, - "jointController": 3, - "jointProcessor": 4, - "coController": 5, -} - -var DataSubjectRoleValues = map[string]int32{ - "DATA_SUBJECT_ROLE_UNSPECIFIED": 0, - "customer": 1, - "employee": 2, -} - -var CookieDurationValues = map[string]int32{ - "COOKIE_DURATION_UNSPECIFIED": 0, - "session": 1, - "persistent": 2, -} - -var CookieProvenanceValues = map[string]int32{ - "COOKIE_TYPE_UNSPECIFIED": 0, - "firstParty": 1, - "thirdParty": 2, -} - -var CookieCategoryValues = map[string]int32{ - "COOKIE_CATEGORY_UNSPECIFIED": 0, - "strictlyNecessary": 1, - "functional": 2, - "performance": 3, - "marketing": 4, -} - -var ParentClosePolicyValues = map[string]int32{ - "terminate": 0, - "requestCancel": 1, - "abandon": 2, -} - -type SelectData struct { - // These are the values that will be selected on this field - Values []*SelectDataValue `yaml:"values,omitempty" json:"values,omitempty"` - // Enter a JSON Array to use. It should be formatted as an array of objects with named properties - Json string `yaml:"json,omitempty" json:"json,omitempty"` - // Enter a url with a data source in JSON Array format. This can be used to populate a Select list with external JSON values - Url string `yaml:"url,omitempty" json:"url,omitempty"` -} - -type SelectDataValue struct { - Value string `yaml:"value,omitempty" json:"value,omitempty"` - Label string `yaml:"label,omitempty" json:"label,omitempty"` -} - -type FormComponent struct { - // The key field is where the data will be saved to. This must be unique per field. - // For example, if key = 'customers' then the value of the field will be saved in data.customers - Name string `yaml:"name,omitempty" json:"name,omitempty"` - // The name or title for this component - Title string `yaml:"title,omitempty" json:"title,omitempty"` - // The type property will be used to select which component to render on the frontend. It cannot be an existing field type - Type string `yaml:"type,omitempty" json:"type,omitempty"` - ShowOnView bool `yaml:"showOnView,omitempty" json:"showOnView,omitempty"` - ShowValueOnEdit bool `yaml:"showValueOnEdit,omitempty" json:"showValueOnEdit,omitempty"` - Editable bool `yaml:"editable,omitempty" json:"editable,omitempty"` - // If true, the field will be required to have a value - Required bool `yaml:"required,omitempty" json:"required,omitempty"` - MinLength int64 `yaml:"minLength,omitempty" json:"minLength,omitempty"` - MaxLength int64 `yaml:"maxLength,omitempty" json:"maxLength,omitempty"` - Pattern string `yaml:"pattern,omitempty" json:"pattern,omitempty"` - // The placeholder text that will appear when this field is empty - Placeholder string `yaml:"placeholder,omitempty" json:"placeholder,omitempty"` - // Default will be the default value for this field, before user interaction. Having a default value will override the placeholder text - Default string `yaml:"default,omitempty" json:"default,omitempty"` - // type == "string" - // This setting will enable spell check on the field if - Spellcheck bool `yaml:"spellcheck,omitempty" json:"spellcheck,omitempty"` - // type == "array" - // If true, multiple values can be added in this field. - // The values will appear as an array in the API and an “Add Another” button will be visible on the field allowing the creation of additional fields for this component - Multiple bool `yaml:"multiple,omitempty" json:"multiple,omitempty"` - // type == "array" - // Data is the definition of how data is provided for the dropdown - Data *SelectData `yaml:"data,omitempty" json:"data,omitempty"` -} - -type Webhook struct { - URL string `yaml:"url" json:"url,omitempty"` - Secret string `yaml:"secret" json:"secret,omitempty"` - Authorization string `yaml:"authorization,omitempty" json:"authorization,omitempty"` - Events []string `yaml:"events,omitempty" json:"events,omitempty"` - TLS TLS `yaml:"tls,omitempty" json:"tls,omitempty"` - MaxQPS int32 `yaml:"maxQPS,omitempty" json:"maxQPS,omitempty"` -} - -// TODO - add rest of TLS properties with proper secrets handling -type TLS struct { - Insecure bool `yaml:"insecure,omitempty" json:"insecure,omitempty"` -} - -type IdentitySpaceFilter struct { - Type string `yaml:"type" json:"type,omitempty"` - Format string `yaml:"format" json:"format,omitempty"` -} - -type IdentitySpaceVariableJWT struct { - Location string `yaml:"location" json:"location"` - Key string `yaml:"key" json:"key"` -} - -type IdentitySpaceVariable struct { - Name string `yaml:"name" json:"name"` - Location string `yaml:"location" json:"location"` - JWT *IdentitySpaceVariableJWT `yaml:"jwt,omitempty" json:"jwt,omitempty"` -} - -type IdentitySpace struct { - Managed bool `yaml:"managed" json:"managed"` - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Filters []*IdentitySpaceFilter `yaml:"filters,omitempty" json:"filters,omitempty"` - Type string `yaml:"type,omitempty" json:"type,omitempty"` - Format string `yaml:"format,omitempty" json:"format,omitempty"` - Variable *IdentitySpaceVariable `yaml:"variable,omitempty" json:"variable,omitempty"` -} - -type AppContact struct { - ContactType string `yaml:"type,omitempty" json:"type,omitempty"` - Email string `yaml:"email,omitempty" json:"email,omitempty"` -} - -type AppConfigContact struct { - ContactType string `yaml:"type,omitempty" json:"type,omitempty"` - Email string `yaml:"email,omitempty" json:"email,omitempty"` -} - -type AppConfigImage struct { - Title string `yaml:"title,omitempty" json:"title,omitempty"` - Link string `yaml:"link,omitempty" json:"link,omitempty"` - Width int32 `yaml:"width,omitempty" json:"width,omitempty"` - Height int32 `yaml:"height,omitempty" json:"height,omitempty"` -} - -type AppConfigActivityStep struct { - ID string `yaml:"id,omitempty" json:"id,omitempty"` - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Step string `yaml:"step,omitempty" json:"step,omitempty"` - Fn string `yaml:"fn,omitempty" json:"fn,omitempty"` - Next string `yaml:"next,omitempty" json:"next,omitempty"` - Options *AppConfigActivityStepOptions `yaml:"options,omitempty" json:"options,omitempty"` - Params *json.RawMessage `yaml:"params,omitempty" json:"params,omitempty"` -} - -type WorkflowStepChildWorkflowOptions struct { - TaskQueue string `yaml:"taskQueue,omitempty" json:"task_queue,omitempty"` - WorkflowExecutionTimeout int64 `yaml:"workflowExecutionTimeout,omitempty" json:"workflow_execution_timeout,omitempty"` - WorkflowRunTimeout int64 `yaml:"workflowRunTimeout,omitempty" json:"workflow_run_timeout,omitempty"` - WorkflowTaskTimeout int64 `yaml:"workflowTaskTimeout,omitempty" json:"workflow_task_timeout,omitempty"` - WaitForCancellation bool `yaml:"waitForCancellation,omitempty" json:"wait_for_cancellation,omitempty"` - ParentClosePolicy int64 `yaml:"parentClosePolicy,omitempty" json:"parent_close_policy,omitempty"` - Memo map[string]string `yaml:"memo,omitempty" json:"memo,omitempty"` - SearchAttributes map[string]string `yaml:"searchAttributes,omitempty" json:"search_attributes,omitempty"` - RetryPolicy *RetryPolicy `yaml:"retryPolicy,omitempty" json:"retry_policy,omitempty"` -} - -type AppConfigChildWorkflowStep struct { - ID string `yaml:"id,omitempty" json:"id,omitempty"` - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Step string `yaml:"step,omitempty" json:"step,omitempty"` - Fn string `yaml:"fn,omitempty" json:"fn,omitempty"` - Next string `yaml:"next,omitempty" json:"next,omitempty"` - Options WorkflowStepChildWorkflowOptions `yaml:"options,omitempty" json:"options,omitempty"` - Params *json.RawMessage `yaml:"params,omitempty" json:"params,omitempty"` -} - -type AppConfigGatewayStep struct { - ID string `yaml:"id,omitempty" json:"id,omitempty"` - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Mode string `yaml:"mode,omitempty" json:"mode,omitempty"` - Next []*StepTransition `yaml:"next,omitempty" json:"next,omitempty"` -} - -type AppConfigActivityOptions struct { - TaskQueue string `yaml:"task_queue,omitempty" json:"task_queue,omitempty"` - WorkflowExecutionTimeout int64 `yaml:"workflow_execution_timeout,omitempty" json:"workflow_execution_timeout,omitempty"` - WorkflowRunTimeout int64 `yaml:"workflow_run_timeout,omitempty" json:"workflow_run_timeout,omitempty"` - WorkflowTaskTimeout int64 `yaml:"workflow_task_timeout,omitempty" json:"workflow_task_timeout,omitempty"` - WaitForCancellation bool `yaml:"wait_for_cancellation,omitempty" json:"wait_for_cancellation,omitempty"` - ScheduleToCloseTimeout int64 `yaml:"schedule_to_close_timeout,omitempty" json:"schedule_to_close_timeout,omitempty"` - ScheduleToStartTimeout int64 `yaml:"schedule_to_start_timeout,omitempty" json:"schedule_to_start_timeout,omitempty"` - StartToCloseTimeout int64 `yaml:"start_to_close_timeout,omitempty" json:"start_to_close_timeout,omitempty"` - HeartbeatTimeout int64 `yaml:"heartbeat_timeout,omitempty" json:"heartbeat_timeout,omitempty"` -} - -type ActivityOptions struct { - TaskQueue string `json:"task_queue,omitempty"` - ScheduleToCloseTimeout int64 `json:"schedule_to_close_timeout,omitempty"` - ScheduleToStartTimeout int64 `json:"schedule_to_start_timeout,omitempty"` - StartToCloseTimeout int64 `json:"start_to_close_timeout,omitempty"` - HeartbeatTimeout int64 `json:"heartbeat_timeout,omitempty"` - WaitForCancellation bool `json:"wait_for_cancellation,omitempty"` - RetryPolicy *RetryPolicy `json:"retry_policy,omitempty"` -} - -type AppConfigActivityStepOptions struct { - TaskQueue string `yaml:"taskQueue,omitempty" json:"task_queue,omitempty"` - ScheduleToCloseTimeout int64 `yaml:"scheduleToCloseTimeout,omitempty" json:"schedule_to_close_timeout,omitempty"` - ScheduleToStartTimeout int64 `yaml:"scheduleToStartTimeout,omitempty" json:"schedule_to_start_timeout,omitempty"` - StartToCloseTimeout int64 `yaml:"startToCloseTimeout,omitempty" json:"start_to_close_timeout,omitempty"` - HeartbeatTimeout int64 `yaml:"heartbeatTimeout,omitempty" json:"heartbeat_timeout,omitempty"` - WaitForCancellation bool `yaml:"waitForCancellation,omitempty" json:"wait_for_cancellation,omitempty"` - RetryPolicy string `yaml:"retryPolicy,omitempty" json:"retry_policy,omitempty"` -} - -type ParameterDefinition struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Type string `yaml:"type,omitempty" json:"type,omitempty"` - Default string `yaml:"default,omitempty" json:"default_value,omitempty"` -} - -type AppConfigWorkflowActivityDefinition struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Icon string `yaml:"icon,omitempty" json:"icon,omitempty"` - Fn string `yaml:"fn,omitempty" json:"fn,omitempty"` - Options *AppConfigActivityOptions `yaml:"options,omitempty" json:"options,omitempty"` - Params []*ParameterDefinition `yaml:"params,omitempty" json:"params,omitempty"` - Outputs []*ParameterDefinition `yaml:"outputs,omitempty" json:"outputs,omitempty"` - Config *json.RawMessage `yaml:"config,omitempty" json:"config,omitempty"` -} - -type IconDefinition struct { - SVG string `json:"SVG,omitempty"` - URL string `json:"URL,omitempty"` - ETag string `json:"ETag,omitempty"` -} - -type ActivityDefinition struct { - Options *ActivityOptions `json:"options,omitempty"` - Params []*ParameterDefinition `json:"params,omitempty"` - Outputs []*ParameterDefinition `json:"outputs,omitempty"` - Config *json.RawMessage `json:"config,omitempty"` - TemporalFunctionName string `json:"temporalFunctionName,omitempty"` -} - -type ChildWorkflowOptions struct { - TaskQueue string `json:"task_queue,omitempty"` - WorkflowExecutionTimeout int64 `json:"workflow_execution_timeout,omitempty"` - WorkflowRunTimeout int64 `json:"workflow_run_timeout,omitempty"` - WorkflowTaskTimeout int64 `json:"workflow_task_timeout,omitempty"` - WaitForCancellation bool `json:"wait_for_cancellation,omitempty"` - Memo map[string]string `json:"memo,omitempty"` - SearchAttributes map[string]string `json:"search_attributes,omitempty"` - RetryPolicy *RetryPolicy `json:"retry_policy,omitempty"` -} - -type ChildWorkflowDefinition struct { - Options *ChildWorkflowOptions `json:"options,omitempty"` - Params []*ParameterDefinition `json:"params,omitempty"` - Outputs []*ParameterDefinition `json:"outputs,omitempty"` - Config *json.RawMessage `json:"config,omitempty"` - TemporalFunctionName string `json:"temporalFunctionName,omitempty"` -} - -type WorkflowActivityDefinition struct { - Code string `json:"code,omitempty"` - Name string `json:"name,omitempty"` - Icon *IconDefinition `json:"icon,omitempty"` - Activity *ActivityDefinition `json:"activity,omitempty"` - Workflow *ChildWorkflowDefinition `json:"workflow,omitempty"` -} - -type PurposeTemplate struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - TcfID int `yaml:"tcfId,omitempty" json:"tcfId,omitempty"` - TcfType string `yaml:"tcfType,omitempty" json:"tcfType,omitempty"` - Editable bool `yaml:"editable,omitempty" json:"editable,omitempty"` - LegalBasisRestriction string `yaml:"legalBasisRestriction,omitempty" json:"legalBasisRestriction,omitempty"` -} - -type Vendor struct { - Id string `yaml:"id,omitempty" json:"id,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Purposes []string `yaml:"purposes,omitempty" json:"purposes,omitempty"` - SpecialPurposes []string `yaml:"specialPurposes,omitempty" json:"specialPurposes,omitempty"` - Features []string `yaml:"features,omitempty" json:"features,omitempty"` - SpecialFeatures []string `yaml:"specialFeatures,omitempty" json:"specialFeatures,omitempty"` - PolicyUrl string `yaml:"policyUrl,omitempty" json:"policyUrl,omitempty"` - LegIntPurposes []string `yaml:"legIntPurposes,omitempty" json:"legIntPurposes,omitempty"` - FlexiblePurposes []string `yaml:"flexiblePurposes,omitempty" json:"flexiblePurposes,omitempty"` - UsesCookies bool `yaml:"usesCookies,omitempty" json:"usesCookies,omitempty"` - CookieMaxAgeSeconds int64 `yaml:"cookieMaxAgeSeconds,omitempty" json:"cookieMaxAgeSeconds,omitempty"` - CookieRefresh bool `yaml:"cookieRefresh,omitempty" json:"cookieRefresh,omitempty"` - UsesNonCookieAccess bool `yaml:"usesNonCookieAccess,omitempty" json:"usesNonCookieAccess,omitempty"` - DeviceStorageDisclosureUrl string `yaml:"deviceStorageDisclosureUrl,omitempty" json:"deviceStorageDisclosureUrl,omitempty"` -} - -type Tcf struct { - Vendor Vendor `yaml:"vendor,omitempty" json:"vendor,omitempty"` - GvlSpecificationVersion string `yaml:"gvlSpecificationVersion,omitempty" json:"gvlSpecificationVersion,omitempty"` - VendorListVersion string `yaml:"vendorListVersion,omitempty" json:"vendorListVersion,omitempty"` - TcfPolicyVersion string `yaml:"tcfPolicyVersion,omitempty" json:"tcfPolicyVersion,omitempty"` -} - -type AppConfigCookie struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Host string `yaml:"host,omitempty" json:"host,omitempty"` - Duration string `yaml:"duration,omitempty" json:"duration,omitempty"` - Provenance string `yaml:"provenance,omitempty" json:"provenance,omitempty"` - Category string `yaml:"category,omitempty" json:"category,omitempty"` - ServiceProvider string `yaml:"serviceProvider,omitempty" json:"serviceProvider,omitempty"` -} - -type Cookie struct { - Code string `json:"code,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - Host string `json:"host,omitempty"` - Duration int32 `json:"duration,omitempty"` - Provenance int32 `json:"provenance,omitempty"` - Category int32 `json:"category,omitempty"` - ServiceProvider string `json:"serviceProvider,omitempty"` - AppCode string `json:"appCode,omitempty"` -} - -type AppConfigPurpose struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - TcfID int `yaml:"tcfId,omitempty" json:"tcfId,omitempty"` - TcfType string `yaml:"tcfType,omitempty" json:"tcfType,omitempty"` - Editable bool `yaml:"editable,omitempty" json:"editable,omitempty"` - LegalBasisRestriction string `yaml:"legalBasisRestriction,omitempty" json:"legalBasisRestriction,omitempty"` - DisplayName string `yaml:"displayName,omitempty" json:"displayName,omitempty"` - DisplayDescription string `yaml:"displayDescription,omitempty" json:"displayDescription,omitempty"` - ProcessingPurpose string `yaml:"processingPurpose,omitempty" json:"processingPurpose,omitempty"` - LegalBasis map[string]string `yaml:"legalBasis,omitempty" json:"legalBasis,omitempty"` - Cookies []*AppConfigCookie `yaml:"cookies,omitempty" json:"cookies,omitempty"` - CanonicalPurposes []string `yaml:"canonicalPurposes,omitempty" json:"canonicalPurposes,omitempty"` - Translations map[string]string `yaml:"translations,omitempty" json:"translations,omitempty"` - DataSubjectRole string `yaml:"dataSubjectRole,omitempty" json:"dataSubjectRole,omitempty"` - DataRole string `yaml:"dataRole,omitempty" json:"dataRole,omitempty"` -} - -type Purpose struct { - Code string `json:"code,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - TcfID int `json:"tcfId,omitempty"` - TcfType string `json:"tcfType,omitempty"` - Editable bool `json:"editable,omitempty"` - LegalBasisRestriction string `json:"legalBasisRestriction,omitempty"` - DisplayName string `json:"displayName,omitempty"` - DisplayDescription string `json:"displayDescription,omitempty"` - ProcessingPurpose string `json:"processingPurpose,omitempty"` - LegalBasis map[string]string `json:"legalBasis,omitempty"` - Cookies []*Cookie `json:"cookies,omitempty"` - CanonicalPurposes []string `json:"canonicalPurposes,omitempty"` - Translations map[string]string `json:"translations,omitempty"` - DataSubjectRole int32 `json:"dataSubjectRole,omitempty"` - DataRole int32 `json:"dataRole,omitempty"` -} - -type RightTranslation struct { - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` -} - -type CanonicalRight struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` -} - -type Right struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Translations map[string]*RightTranslation `yaml:"translations,omitempty" json:"translations,omitempty"` - CanonicalRights []*CanonicalRight `yaml:"canonicalRights,omitempty" json:"canonicalRights,omitempty"` -} - -type Regulation struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - RightsFulfillment []*RightFulfillment `yaml:"rightsFulfillment,omitempty" json:"rightsFulfillment,omitempty"` -} - -type LegalBasisRestriction struct { - Regulation string `yaml:"regulation,omitempty" json:"regulation,omitempty"` - LegalBasis []string `yaml:"legalBasis,omitempty" json:"legalBasis,omitempty"` -} - -type AppConfigPolicyScope struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Regions []string `yaml:"regions,omitempty" json:"regions,omitempty"` - Regulations []string `yaml:"regulations,omitempty" json:"regulations,omitempty"` - Fulfillment map[string]int64 `yaml:"fulfillment,omitempty" json:"fulfillment,omitempty"` -} - -type RightFulfillment struct { - RightCode string `json:"rightCode,omitempty"` - Fulfillment int64 `json:"fulfillment,omitempty"` -} - -type PolicyScope struct { - Code string `json:"code,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - RegionCodes []string `json:"regionCodes,omitempty"` - RegulationCodes []string `json:"regulationCodes,omitempty"` - RightsFulfillment []*RightFulfillment `json:"rightsFulfillment,omitempty"` -} - -type AppConfigLegalBasis struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - RequiresOptIn bool `yaml:"requiresOptIn,omitempty" json:"requiresOptIn,omitempty"` - AllowOptOut bool `yaml:"allowOptOut,omitempty" json:"allowOptOut,omitempty"` - RequiresPrivacyPolicy bool `yaml:"requiresPrivacyPolicy,omitempty" json:"requiresPrivacyPolicy,omitempty"` -} - -type LegalBasis struct { - Code string `json:"code,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - RequiresOptIn bool `json:"requiresOptIn,omitempty"` - AllowOptOut bool `json:"allowOptOut,omitempty"` - RequiresPrivacyPolicy bool `json:"requiresPrivacyPolicy,omitempty"` - RegulationCodes []string `json:"regulationCodes,omitempty"` -} - -type Theme struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - BannerBackgroundColor string `yaml:"bannerBackgroundColor,omitempty" json:"bannerBackgroundColor,omitempty"` - LightboxRibbonColor string `yaml:"lightboxRibbonColor,omitempty" json:"lightboxRibbonColor,omitempty"` - FormHeaderColor string `yaml:"formHeaderColor,omitempty" json:"formHeaderColor,omitempty"` - StatusColor string `yaml:"statusColor,omitempty" json:"statusColor,omitempty"` - HighlightColor string `yaml:"highlightColor,omitempty" json:"highlightColor,omitempty"` - FeedbackColor string `yaml:"feedbackColor,omitempty" json:"feedbackColor,omitempty"` -} - -type RetryPolicy struct { - InitialInterval int64 `yaml:"initialInterval,omitempty" json:"initial_interval,omitempty"` - BackoffCoefficient float64 `yaml:"backoffCoefficient,omitempty" json:"backoff_coefficient,omitempty"` - MaximumInterval int64 `yaml:"maximumInterval,omitempty" json:"maximum_interval,omitempty"` - MaximumAttempts int64 `yaml:"maximumAttempts,omitempty" json:"maximum_attempts,omitempty"` - NonRetryableErrorReasons []string `yaml:"nonRetryableErrorReasons,omitempty" json:"non_retriable_error_reasons,omitempty"` -} - -type WorkflowOptions struct { - TaskQueue string `yaml:"taskQueue,omitempty" json:"task_queue,omitempty"` - WorkflowExecutionTimeout int64 `yaml:"workflowExecutionTimeout,omitempty" json:"workflow_execution_timeout,omitempty"` - WorkflowRunTimeout int64 `yaml:"workflowRunTimeout,omitempty" json:"workflow_run_timeout,omitempty"` - WorkflowTaskTimeout int64 `yaml:"workflowTaskTimeout,omitempty" json:"workflow_task_timeout,omitempty"` - Memo map[string]string `yaml:"memo,omitempty" json:"memo,omitempty"` - SearchAttributes map[string]string `yaml:"searchAttributes,omitempty" json:"search_attributes,omitempty"` - RetryPolicy *RetryPolicy `yaml:"retryPolicy,omitempty" json:"retry_policy,omitempty"` -} - -type AppConfigStep struct { - Activity *AppConfigActivityStep `yaml:"activity,omitempty" json:"activity,omitempty"` - ChildWorkflow *AppConfigChildWorkflowStep `yaml:"childWorkflow,omitempty" json:"childWorkflow,omitempty"` - Gateway *AppConfigGatewayStep `yaml:"gateway,omitempty" json:"gateway,omitempty"` - Start *AppConfigStartStep `yaml:"start,omitempty" json:"start,omitempty"` - Finish *AppConfigFinishStep `yaml:"finish,omitempty" json:"finish,omitempty"` -} - -type AppConfigStartStep struct { - ID string `yaml:"id,omitempty" json:"id,omitempty"` - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Next string `yaml:"next,omitempty" json:"next,omitempty"` - Params *json.RawMessage `yaml:"params,omitempty" json:"params,omitempty"` -} - -type AppConfigFinishStep struct { - ID string `yaml:"id,omitempty" json:"id,omitempty"` - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Description string `yaml:"description,omitempty" json:"description,omitempty"` - Params *json.RawMessage `yaml:"params,omitempty" json:"params,omitempty"` -} - -type StepTransition struct { - ID string `yaml:"id,omitempty" json:"id,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Variable string `yaml:"variable,omitempty" json:"variable,omitempty"` - Operator string `yaml:"operator,omitempty" json:"operator,omitempty"` - Operand string `yaml:"operand,omitempty" json:"operand,omitempty"` -} - -type AppConfigWorkflowDefinition struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Readonly bool `yaml:"readonly,omitempty" json:"readonly,omitempty"` - Options *WorkflowOptions `yaml:"options,omitempty" json:"options,omitempty"` - Steps []*AppConfigStep `yaml:"steps,omitempty" json:"steps,omitempty"` -} - -type ActivityStep struct { - Code string `json:"code,omitempty"` - Options *ActivityOptions `json:"options,omitempty"` - Params *json.RawMessage `json:"params,omitempty"` - Transition string `json:"transition,omitempty"` - TemporalFunctionName string `json:"temporalFunctionName,omitempty"` -} - -type ChildWorkflowStep struct { - Code string `json:"code,omitempty"` - Options *ChildWorkflowOptions `json:"options,omitempty"` - Params *json.RawMessage `json:"params,omitempty"` - Transition string `json:"transition,omitempty"` - TemporalFunctionName string `json:"temporalFunctionName,omitempty"` -} - -var GatewayStepModeValues = map[string]int32{ - "invalid": 0, - "split": 1, - "join": 2, - "single": 3, - "multi": 4, -} - -type GatewayStep struct { - Mode int32 `json:"mode,omitempty"` - Transitions []*StepTransition `json:"transitions,omitempty"` -} - -type StartStep struct { - Transition string `json:"transition,omitempty"` - Params *json.RawMessage `json:"params,omitempty"` -} - -type FinishStep struct { - Params *json.RawMessage `json:"params,omitempty"` -} - -type Step struct { - ID string `json:"ID,omitempty"` - Code string `json:"code,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - Activity *ActivityStep `json:"activity,omitempty"` - Workflow *ChildWorkflowStep `json:"workflow,omitempty"` - Gateway *GatewayStep `json:"gateway,omitempty"` - Start *StartStep `json:"start,omitempty"` - Finish *FinishStep `json:"finish,omitempty"` -} - -type WorkflowDefinition struct { - Code string `yaml:"code,omitempty" json:"code,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Readonly bool `yaml:"readonly,omitempty" json:"readonly,omitempty"` - Options *WorkflowOptions `yaml:"options,omitempty" json:"options,omitempty"` - Steps []*Step `yaml:"steps,omitempty" json:"steps,omitempty"` -} - -type ManifestInputs struct { - ID string `yaml:"ID,omitempty" json:"ID,omitempty"` - Code string `yaml:"code,omitempty" json:"code,omitempty"` - OrgCode string `yaml:"org,omitempty" json:"org,omitempty"` - Name string `yaml:"name,omitempty" json:"name,omitempty"` - Version string `yaml:"version,omitempty" json:"version,omitempty"` - Depends string `yaml:"depends,omitempty" json:"depends,omitempty"` - Provides []string `yaml:"provides,omitempty" json:"provides,omitempty"` - Type AppType `yaml:"type,omitempty" json:"type,omitempty"` - AutoUpgrade bool `yaml:"autoUpgrade,omitempty" json:"autoUpgrade,omitempty"` - Instances string `yaml:"instances,omitempty" json:"instances,omitempty"` - PrimaryCategory string `yaml:"primaryCategory,omitempty" json:"primaryCategory,omitempty"` - SecondaryCategory string `yaml:"secondaryCategory,omitempty" json:"secondaryCategory,omitempty"` - Rules map[string]string `yaml:"rules" json:"rules,omitempty"` - Capabilities []string `yaml:"capabilities,omitempty" json:"capabilities,omitempty"` - SupportedLanguages []string `yaml:"supportedLanguages,omitempty" json:"supportedLanguages,omitempty"` - SupportedPurposes []string `yaml:"supportedPurposes,omitempty" json:"supportedPurposes,omitempty"` - SupportedRights []string `yaml:"supportedRights,omitempty" json:"supportedRights,omitempty"` - ShortDescription string `yaml:"shortDescription,omitempty" json:"shortDescription,omitempty"` - DetailedDescription string `yaml:"detailedDescription,omitempty" json:"detailedDescription,omitempty"` - PermissionNote string `yaml:"permissionNote,omitempty" json:"permissionNote,omitempty"` - Permissions []string `yaml:"permissions,omitempty" json:"permissions,omitempty"` - InfoUrl string `yaml:"infoURL,omitempty" json:"infoURL,omitempty"` - SetupUrl string `yaml:"setupURL,omitempty" json:"setupURL,omitempty"` - HomepageUrl string `yaml:"homepageURL,omitempty" json:"homepageURL,omitempty"` - CustomerSupportUrl string `yaml:"customerSupportURL,omitempty" json:"customerSupportURL,omitempty"` - PrivacyPolicyUrl string `yaml:"privacyPolicyURL,omitempty" json:"privacyPolicyURL,omitempty"` - StatusUrl string `yaml:"statusURL,omitempty" json:"statusURL,omitempty"` - TosUrl string `yaml:"tosURL,omitempty" json:"tosURL,omitempty"` - DocUrl string `yaml:"docURL,omitempty" json:"docURL,omitempty"` - Logo *AppConfigImage `yaml:"logo,omitempty" json:"logo,omitempty"` - Previews []*AppConfigImage `yaml:"previews,omitempty" json:"previews,omitempty"` - Contacts []*AppConfigContact `yaml:"contacts,omitempty" json:"contacts,omitempty"` - ExpireUserTokens bool `yaml:"expireUserTokens,omitempty" json:"expireUserTokens,omitempty"` - RefreshInterval string `yaml:"refreshInterval,omitempty" json:"refreshInterval,omitempty"` - RequestUserAuth bool `yaml:"requestUserAuth,omitempty" json:"requestUserAuth,omitempty"` - UserAuthCallbackUrl string `yaml:"userAuthCallbackURL,omitempty" json:"userAuthCallbackURL,omitempty"` - RedirectOnUpdate bool `yaml:"redirectOnUpdate,omitempty" json:"redirectOnUpdate,omitempty"` - Webhook *Webhook `yaml:"webhook,omitempty" json:"webhook,omitempty"` - Form []*FormComponent `yaml:"form,omitempty" json:"form,omitempty"` - IdentitySpaces []*IdentitySpace `yaml:"identitySpaces,omitempty" json:"identitySpaces,omitempty"` - Workflows []*AppConfigWorkflowDefinition `yaml:"workflows,flow,omitempty" json:"workflows,omitempty"` - Activities []*AppConfigWorkflowActivityDefinition `yaml:"activities,flow,omitempty" json:"activities,omitempty"` - ChildWorkflows []*AppConfigWorkflowActivityDefinition `yaml:"childWorkflows,flow,omitempty" json:"childWorkflows,omitempty"` - Tcf *Tcf `yaml:"tcf,flow,omitempty" json:"tcf,omitempty"` - Cookies []*AppConfigCookie `yaml:"cookies,flow,omitempty" json:"cookies,omitempty"` - PurposeTemplates []*PurposeTemplate `yaml:"purposeTemplateCollections,flow,omitempty" json:"purposeTemplateCollections,omitempty"` - Purposes []*AppConfigPurpose `yaml:"purposes,flow,omitempty" json:"purposes,omitempty"` - Rights []*Right `yaml:"rights,flow" json:"rights,omitempty"` - Regulations []*Regulation `yaml:"regulations,flow" json:"regulations,omitempty"` - LegalBasisRestrictions []*LegalBasisRestriction `yaml:"legalBasisRestrictions,flow,omitempty" json:"legalBasisRestrictions,omitempty"` - PolicyScopes []*AppConfigPolicyScope `yaml:"policyScopes,flow,omitempty" json:"policyScopes,omitempty"` - LegalBases []*AppConfigLegalBasis `yaml:"legalBases,flow,omitempty" json:"legalBases,omitempty"` - Themes []*Theme `yaml:"themes,flow,omitempty" json:"themes,omitempty"` -} - -type App struct { - ID string `json:"id,omitempty"` - Code string `json:"code,omitempty"` - OrgCode string `yaml:"orgCode" json:"orgCode,omitempty"` - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` - Depends string `json:"depends,omitempty"` - Provides []string `json:"provides,omitempty"` - Type int32 `json:"type,omitempty"` - AutoUpgrade bool `json:"autoUpgrade,omitempty"` - Instances int32 `json:"instances,omitempty"` - Rules map[string]string `yaml:",flow" json:"rules,omitempty"` - Capabilities []int32 `yaml:",flow" json:"capabilities,omitempty"` - SupportedLanguages []string `yaml:",flow" json:"supportedLanguages,omitempty"` - SupportedPurposes []string `yaml:",flow" json:"supportedPurposes,omitempty"` - SupportedRights []string `yaml:",flow" json:"supportedRights,omitempty"` - PermissionNote string `json:"permissionNode,omitempty"` - Permissions []string `yaml:",flow"` - InfoUrl string `json:"infoURL,omitempty"` - SetupUrl string `json:"setupURL,omitempty"` - HomepageUrl string `json:"homepageURL,omitempty"` - ExpireUserTokens bool `json:"expireUserTokens,omitempty"` - RefreshInterval int64 `yaml:"refreshInterval" json:"refreshInterval,omitempty"` - RequestUserAuth bool `json:"requestUserAuth,omitempty"` - UserAuthCallbackUrl string `json:"userAuthCallbackURL,omitempty"` - RedirectOnUpdate bool `json:"redirectOnUpdate,omitempty"` - WebhookId string `json:"webhookID,omitempty"` - Readme string `json:"readme,omitempty"` - Form []*FormComponent `yaml:",flow"` - IdentitySpaces []*IdentitySpace `yaml:",flow" json:"identitySpaces,omitempty"` - Purposes []*Purpose `yaml:",flow" json:"purposes,omitempty"` - Workflows []*WorkflowDefinition `json:"workflows,omitempty"` - Activities []*WorkflowActivityDefinition `json:"activities,omitempty"` - ChildWorkflows []*WorkflowActivityDefinition `json:"childWorkflows,omitempty"` - PurposeTemplates []*PurposeTemplate `json:"purposeTemplates,omitempty"` - LegalBasisRestrictions []*LegalBasisRestriction `json:"legalBasisRestrictions,omitempty"` - PolicyScopes []*PolicyScope `json:"policyScopes,omitempty"` - LegalBases []*LegalBasis `json:"legalBases,omitempty"` - Themes []*Theme `json:"themes,omitempty"` - Rights []*Right `yaml:",flow" json:"rights,omitempty"` - Regulations []*Regulation `yaml:",flow" json:"regulations,omitempty"` - Tcf *Tcf `json:"tcf,omitempty"` - EventTypes []string `json:"eventTypes,omitempty"` - Cookies []*Cookie `yaml:"cookies,flow,omitempty" json:"cookies,omitempty"` -} - -type AppMarketplaceEntry struct { - AppCode string `json:"appCode,omitempty"` - AppID string `json:"appID,omitempty"` - Version string `json:"version,omitempty"` - Contacts []*AppContact `yaml:",flow"` - ShortDescription string `json:"shortDescription,omitempty"` - PrimaryCategory int32 `yaml:",inline" json:"primaryCategory,omitempty"` - SecondaryCategory int32 `yaml:",inline" json:"secondaryCategory,omitempty"` - SupportedLanguages []string `yaml:",flow" json:"supportedLanguages,omitempty"` - CustomerSupportUrl string `json:"customerSupportURL,omitempty"` - PrivacyPolicyUrl string `json:"privacyPolicyURL,omitempty"` - StatusUrl string `json:"statusURL,omitempty"` - TosUrl string `json:"tosURL,omitempty"` - DocUrl string `json:"docURL,omitempty"` - Logo Image `yaml:",flow"` - IntroDescription string `json:"introDescription,omitempty"` - DetailedDescription string `json:"detailedDescription,omitempty"` - Previews []*Image `yaml:",flow" json:"previews,omitempty"` -} - -type Image struct { - Data []byte `yaml:"data" json:"data,omitempty"` - Title string `yaml:"title" json:"title,omitempty"` - Url string `yaml:"url" json:"url,omitempty"` - Width int32 `yaml:"width" json:"width,omitempty"` - Height int32 `yaml:"height" json:"height,omitempty"` -} - -type PublishAppRequest struct { - AppMarketplaceEntry *AppMarketplaceEntry `json:"marketplaceEntry,omitempty"` - Webhook *Webhook `json:"webhook,omitempty"` -} - -type PublishAppResponse struct { - AppMarketplaceEntry *AppMarketplaceEntry `json:"marketplaceEntry,omitempty"` -} - -type WebhookResponse struct { - Webhook *Webhook -} - -type PutAppRequest struct { - App *App -} - -type PutAppResponse struct { - App *App -} - -func NewApp(p ManifestInputs) (*App, error) { - var appCapabilities []int32 - for _, capability := range p.Capabilities { - if appCapability, ok := AppCapabilityValues[capability]; ok { - appCapabilities = append(appCapabilities, appCapability) - } - } - - var refreshIntervalHours int64 - if len(p.RefreshInterval) > 0 { - refreshIntervalNanoseconds, err := time.ParseDuration(p.RefreshInterval) - if err != nil { - return nil, err - } - refreshIntervalHours = int64(refreshIntervalNanoseconds / time.Hour) - } - - var policyScopes []*PolicyScope - for _, policyScope := range p.PolicyScopes { - var rightsFulfillment []*RightFulfillment - for rightCode, fulfillment := range policyScope.Fulfillment { - rightsFulfillment = append(rightsFulfillment, &RightFulfillment{ - RightCode: rightCode, - Fulfillment: fulfillment, - }) - } - - policyScopes = append(policyScopes, &PolicyScope{ - Code: policyScope.Code, - Name: policyScope.Name, - Description: policyScope.Description, - RegionCodes: policyScope.Regions, - RegulationCodes: policyScope.Regulations, - RightsFulfillment: rightsFulfillment, - }) - } - - var legalBases []*LegalBasis - for _, legalBasis := range p.LegalBases { - legalBases = append(legalBases, &LegalBasis{ - Code: legalBasis.Code, - Name: legalBasis.Name, - Description: legalBasis.Description, - RequiresOptIn: legalBasis.RequiresOptIn, - AllowOptOut: legalBasis.AllowOptOut, - RequiresPrivacyPolicy: legalBasis.RequiresPrivacyPolicy, - }) - } - - var purposes []*Purpose - for _, purpose := range p.Purposes { - var cookies []*Cookie - for _, cookie := range purpose.Cookies { - cookies = append(cookies, &Cookie{ - Code: cookie.Code, - Name: cookie.Name, - Description: cookie.Description, - Host: cookie.Host, - Duration: CookieDurationValues[cookie.Duration], - Provenance: CookieProvenanceValues[cookie.Provenance], - Category: CookieCategoryValues[cookie.Category], - ServiceProvider: cookie.ServiceProvider, - }) - } - - purposes = append(purposes, &Purpose{ - Code: purpose.Code, - Name: purpose.Name, - Description: purpose.Description, - TcfID: purpose.TcfID, - TcfType: purpose.TcfType, - Editable: purpose.Editable, - LegalBasisRestriction: purpose.LegalBasisRestriction, - DisplayName: purpose.DisplayName, - DisplayDescription: purpose.DisplayDescription, - ProcessingPurpose: purpose.ProcessingPurpose, - LegalBasis: purpose.LegalBasis, - Cookies: cookies, - CanonicalPurposes: purpose.CanonicalPurposes, - Translations: purpose.Translations, - DataSubjectRole: DataSubjectRoleValues[purpose.DataSubjectRole], - DataRole: DataRoleValues[purpose.DataRole], - }) - } - - var workflows []*WorkflowDefinition - for _, workflow := range p.Workflows { - var steps []*Step - for _, appConfigStep := range workflow.Steps { - step := &Step{} - - if appConfigStep.Start != nil { - step.ID = appConfigStep.Start.ID - step.Code = appConfigStep.Start.Code - step.Description = appConfigStep.Start.Description - step.Start = &StartStep{ - Transition: appConfigStep.Start.Next, - Params: appConfigStep.Start.Params, - } - } else if appConfigStep.Finish != nil { - step.ID = appConfigStep.Finish.ID - step.Code = appConfigStep.Finish.Code - step.Description = appConfigStep.Finish.Description - step.Finish = &FinishStep{ - Params: appConfigStep.Finish.Params, - } - } else if appConfigStep.Activity != nil { - step.ID = appConfigStep.Activity.ID - step.Code = appConfigStep.Activity.Code - step.Description = appConfigStep.Activity.Description - step.Activity = &ActivityStep{ - Code: appConfigStep.Activity.Code, - Options: &ActivityOptions{ - TaskQueue: appConfigStep.Activity.Options.TaskQueue, - ScheduleToCloseTimeout: appConfigStep.Activity.Options.ScheduleToCloseTimeout, - ScheduleToStartTimeout: appConfigStep.Activity.Options.ScheduleToStartTimeout, - StartToCloseTimeout: appConfigStep.Activity.Options.StartToCloseTimeout, - HeartbeatTimeout: appConfigStep.Activity.Options.HeartbeatTimeout, - WaitForCancellation: appConfigStep.Activity.Options.WaitForCancellation, - }, - Params: appConfigStep.Activity.Params, - Transition: appConfigStep.Activity.Next, - TemporalFunctionName: appConfigStep.Activity.Fn, - } - } else if appConfigStep.ChildWorkflow != nil { - step.ID = appConfigStep.ChildWorkflow.ID - step.Code = appConfigStep.ChildWorkflow.Code - step.Description = appConfigStep.ChildWorkflow.Description - step.Workflow = &ChildWorkflowStep{ - Code: appConfigStep.ChildWorkflow.Code, - Options: &ChildWorkflowOptions{ - TaskQueue: appConfigStep.ChildWorkflow.Options.TaskQueue, - WorkflowExecutionTimeout: appConfigStep.ChildWorkflow.Options.WorkflowExecutionTimeout, - WorkflowRunTimeout: appConfigStep.ChildWorkflow.Options.WorkflowRunTimeout, - WorkflowTaskTimeout: appConfigStep.ChildWorkflow.Options.WorkflowTaskTimeout, - WaitForCancellation: appConfigStep.ChildWorkflow.Options.WaitForCancellation, - Memo: appConfigStep.ChildWorkflow.Options.Memo, - SearchAttributes: appConfigStep.ChildWorkflow.Options.SearchAttributes, - RetryPolicy: appConfigStep.ChildWorkflow.Options.RetryPolicy, - }, - Params: appConfigStep.ChildWorkflow.Params, - Transition: appConfigStep.ChildWorkflow.Next, - TemporalFunctionName: appConfigStep.ChildWorkflow.Fn, - } - } else if appConfigStep.Gateway != nil { - step.ID = appConfigStep.Gateway.ID - step.Code = appConfigStep.Gateway.Code - step.Description = appConfigStep.Gateway.Description - step.Gateway = &GatewayStep{ - Mode: GatewayStepModeValues[appConfigStep.Gateway.Mode], - Transitions: appConfigStep.Gateway.Next, - } - } - - steps = append(steps, step) - } - - workflows = append(workflows, &WorkflowDefinition{ - Code: workflow.Code, - Name: workflow.Name, - Readonly: workflow.Readonly, - Options: workflow.Options, - Steps: steps, - }) - } - - var activities []*WorkflowActivityDefinition - for _, activity := range p.Activities { - // TODO: Upload icon - icon := &IconDefinition{} - - activities = append(activities, &WorkflowActivityDefinition{ - Code: activity.Code, - Name: activity.Name, - Icon: icon, - Activity: &ActivityDefinition{ - Options: &ActivityOptions{ - TaskQueue: activity.Options.TaskQueue, - ScheduleToCloseTimeout: activity.Options.ScheduleToCloseTimeout, - ScheduleToStartTimeout: activity.Options.ScheduleToStartTimeout, - StartToCloseTimeout: activity.Options.StartToCloseTimeout, - HeartbeatTimeout: activity.Options.HeartbeatTimeout, - WaitForCancellation: activity.Options.WaitForCancellation, - }, - Params: activity.Params, - Outputs: activity.Outputs, - Config: activity.Config, - TemporalFunctionName: activity.Fn, - }, - }) - } - - var childWorkflows []*WorkflowActivityDefinition - for _, childWorkflow := range p.ChildWorkflows { - // TODO: Upload icon - icon := &IconDefinition{} - - childWorkflows = append(childWorkflows, &WorkflowActivityDefinition{ - Code: childWorkflow.Code, - Name: childWorkflow.Name, - Icon: icon, - Workflow: &ChildWorkflowDefinition{ - Options: &ChildWorkflowOptions{ - TaskQueue: childWorkflow.Options.TaskQueue, - WorkflowExecutionTimeout: childWorkflow.Options.WorkflowExecutionTimeout, - WorkflowRunTimeout: childWorkflow.Options.WorkflowRunTimeout, - WorkflowTaskTimeout: childWorkflow.Options.WorkflowTaskTimeout, - WaitForCancellation: childWorkflow.Options.WaitForCancellation, - }, - Params: childWorkflow.Params, - Outputs: childWorkflow.Outputs, - Config: childWorkflow.Config, - TemporalFunctionName: childWorkflow.Fn, - }, - }) - } - - var eventTypes []string - if p.Webhook != nil { - eventTypes = p.Webhook.Events - } - - var cookies []*Cookie - for _, cookie := range p.Cookies { - cookies = append(cookies, &Cookie{ - Code: cookie.Code, - Name: cookie.Name, - Description: cookie.Description, - Host: cookie.Host, - Duration: CookieDurationValues[cookie.Duration], - Provenance: CookieProvenanceValues[cookie.Provenance], - Category: CookieCategoryValues[cookie.Category], - ServiceProvider: cookie.ServiceProvider, - AppCode: p.Code, - }) - } - - return &App{ - ID: p.ID, - Code: p.Code, - OrgCode: p.OrgCode, - Name: p.Name, - Version: p.Version, - Depends: p.Depends, - Provides: p.Provides, - Type: AppTypeValues[p.Type], - AutoUpgrade: p.AutoUpgrade, - Instances: AppAllowedInstancesValues[p.Instances], - Rules: p.Rules, - Capabilities: appCapabilities, - SupportedLanguages: p.SupportedLanguages, - SupportedPurposes: p.SupportedPurposes, - SupportedRights: p.SupportedRights, - PermissionNote: p.PermissionNote, - Permissions: p.Permissions, - InfoUrl: p.InfoUrl, - SetupUrl: p.SetupUrl, - HomepageUrl: p.HomepageUrl, - ExpireUserTokens: p.ExpireUserTokens, - RefreshInterval: refreshIntervalHours, - RequestUserAuth: p.RequestUserAuth, - UserAuthCallbackUrl: p.UserAuthCallbackUrl, - RedirectOnUpdate: p.RedirectOnUpdate, - Form: p.Form, - IdentitySpaces: p.IdentitySpaces, - Purposes: purposes, - Rights: p.Rights, - Regulations: p.Regulations, - Tcf: p.Tcf, - Workflows: workflows, - Activities: activities, - ChildWorkflows: childWorkflows, - PurposeTemplates: p.PurposeTemplates, - LegalBasisRestrictions: p.LegalBasisRestrictions, - PolicyScopes: policyScopes, - LegalBases: legalBases, - Themes: p.Themes, - EventTypes: eventTypes, - Cookies: cookies, - }, nil -} - -func NewAppMarketplaceEntry(p ManifestInputs) *AppMarketplaceEntry { - var appCapabilities []int32 - for _, capability := range p.Capabilities { - if appCapability, ok := AppCapabilityValues[capability]; ok { - appCapabilities = append(appCapabilities, appCapability) - } - } - - var appContacts []*AppContact - for _, contact := range p.Contacts { - appContacts = append(appContacts, &AppContact{ - ContactType: contact.ContactType, - Email: contact.Email, - }) - } - - primaryCategory := AppMarketplaceCategoryValues[p.PrimaryCategory] - secondaryCategory := AppMarketplaceCategoryValues[p.SecondaryCategory] - - return &AppMarketplaceEntry{ - AppCode: p.Code, - Version: p.Version, - Contacts: appContacts, - ShortDescription: p.ShortDescription, - PrimaryCategory: primaryCategory, - SecondaryCategory: secondaryCategory, - SupportedLanguages: p.SupportedLanguages, - CustomerSupportUrl: p.CustomerSupportUrl, - PrivacyPolicyUrl: p.PrivacyPolicyUrl, - StatusUrl: p.StatusUrl, - TosUrl: p.TosUrl, - DocUrl: p.DocUrl, - Logo: Image{}, - IntroDescription: p.ShortDescription, - DetailedDescription: p.DetailedDescription, - } -} diff --git a/apps/publish.go b/apps/publish.go deleted file mode 100644 index 32ac1bb..0000000 --- a/apps/publish.go +++ /dev/null @@ -1,487 +0,0 @@ -package apps - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "github.com/spf13/cobra" - "github.com/xeipuuv/gojsonschema" - "go.ketch.com/cli/ketch-cli/assets" - "go.ketch.com/cli/ketch-cli/config" - "go.ketch.com/cli/ketch-cli/flags" - "go.ketch.com/lib/orlop" - "go.ketch.com/lib/orlop/errors" - "gopkg.in/yaml.v3" - "io/ioutil" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "strings" -) - -func Publish(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - - appConfig, err := cmd.Flags().GetString(flags.File) - if err != nil { - return err - } - - versionCliArg, err := cmd.Flags().GetString(flags.Version) - if err != nil { - return err - } - - token, err := cmd.Flags().GetString(flags.Token) - if err != nil { - return err - } - - rootUrl, err := cmd.Flags().GetString(flags.URL) - if err != nil { - return err - } - - t, err := config.GetTLSConfig(cmd) - if err != nil { - return err - } - - appConfig, err = filepath.Abs(appConfig) - if err != nil { - return err - } - - basePath := filepath.Dir(appConfig) - if err = os.Chdir(basePath); err != nil { - return err - } - - b, err := ioutil.ReadFile(appConfig) - if err != nil { - return err - } - - b = []byte(os.ExpandEnv(string(b))) - - var manifestInputs ManifestInputs - if err := yaml.Unmarshal(b, &manifestInputs); err != nil { - return err - } - - if len(versionCliArg) > 0 { - manifestInputs.Version = versionCliArg - } - - if err := validateAppConfig(manifestInputs); err != nil { - return err - } - - cfg := config.GetFromContext(ctx) - - cfg.URL = rootUrl - cfg.TLS = *t - - app, err := NewApp(manifestInputs) - if err != nil { - return err - } - - if len(app.Version) == 0 { - return errors.New("app version must be specified via cli --version or via manifest") - } - - app, err = createApp(ctx, cfg, token, app) - if err != nil { - return err - } - - marketplaceEntry := NewAppMarketplaceEntry(manifestInputs) - marketplaceEntry.AppID = app.ID - - if len(manifestInputs.Logo.Link) > 0 { - marketplaceEntry.Logo = Image{ - Title: manifestInputs.Logo.Title, - Width: manifestInputs.Logo.Width, - Height: manifestInputs.Logo.Height, - } - - if marketplaceEntry.Logo.Data, err = getFileData(manifestInputs.Logo.Link); err != nil { - return err - } - } - - if len(manifestInputs.Previews) > 0 { - var previews []*Image - - for _, preview := range manifestInputs.Previews { - previewImage := &Image{ - Title: preview.Title, - Width: preview.Width, - Height: preview.Height, - } - - if previewImage.Data, err = getFileData(preview.Link); err != nil { - return err - } - - previews = append(previews, previewImage) - } - - marketplaceEntry.Previews = previews - } - - published, err := publishApp(ctx, cfg, token, app, marketplaceEntry, manifestInputs.Webhook) - if err != nil { - return err - } - - fmt.Printf("app published successfully:\nappCode: %s\nappID: %s\nappVersion: %s\n", app.Code, app.ID, published.Version) - - return nil -} - -func handleRestResponseError(resp *http.Response) (*Error, error) { - var respErr *ErrorResponse - err := json.NewDecoder(resp.Body).Decode(&respErr) - if err != nil { - return nil, err - } - - return respErr.Error, nil -} - -func callRest(ctx context.Context, cfg *config.Config, method, urlPath, token string, body []byte) (*http.Response, error) { - u, err := url.Parse(cfg.URL) - if err != nil { - return nil, err - } - - u.Path = path.Join(u.Path, "rest", "v1", urlPath) - - req, err := http.NewRequestWithContext(ctx, method, u.String(), bytes.NewReader(body)) - if err != nil { - return nil, err - } - - req.Header.Add("Authorization", "Bearer "+token) - req.Header.Add("Accept", "application/json") - req.Header.Add("Content-Type", "application/json") - - tp := http.DefaultTransport.(*http.Transport).Clone() - tp.TLSClientConfig, err = orlop.NewClientTLSConfigContext(ctx, cfg.TLS, cfg.Vault) - if err != nil { - return nil, err - } - - cli := &http.Client{ - Transport: tp, - } - - return cli.Do(req) -} - -func createApp(ctx context.Context, cfg *config.Config, token string, app *App) (*App, error) { - createAppURL := fmt.Sprintf("organizations/%s/apps", app.OrgCode) - - body, err := json.Marshal(&PutAppRequest{ - App: app, - }) - if err != nil { - return nil, err - } - - resp, err := callRest(ctx, cfg, http.MethodPost, createAppURL, token, body) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - respErr, err := handleRestResponseError(resp) - if err != nil { - return nil, err - } - - return nil, errors.New(respErr.Message) - } - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var appResp PutAppResponse - err = json.Unmarshal(b, &appResp) - if err != nil { - return nil, err - } - - if appResp.App == nil || len(appResp.App.ID) == 0 { - return nil, errors.Errorf("app not created. statusCode %v, body %v", resp.StatusCode, string(b)) - } - - fmt.Printf("app created successfully:\napp: %v", string(body)) - - return appResp.App, nil -} - -func publishApp(ctx context.Context, cfg *config.Config, token string, app *App, marketplaceEntry *AppMarketplaceEntry, webhook *Webhook) (*AppMarketplaceEntry, error) { - publishURL := fmt.Sprintf("organizations/%s/apps/%s/publish", app.OrgCode, app.ID) - - body, err := json.Marshal(&PublishAppRequest{ - AppMarketplaceEntry: marketplaceEntry, - Webhook: webhook, - }) - if err != nil { - return nil, err - } - - resp, err := callRest(ctx, cfg, http.MethodPost, publishURL, token, body) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - respErr, err := handleRestResponseError(resp) - if err != nil { - return nil, err - } - - return nil, errors.New(respErr.Message) - } - - respBody, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var a PublishAppResponse - err = json.Unmarshal(respBody, &a) - if err != nil { - return nil, err - } - - if a.AppMarketplaceEntry == nil || len(a.AppMarketplaceEntry.AppID) == 0 { - return nil, errors.Errorf("app marketplace entry not created. statusCode %v, body %v", resp.StatusCode, string(respBody)) - } - - return a.AppMarketplaceEntry, nil -} - -func validateAppConfig(publishAppConfig ManifestInputs) error { - manifestSchema := assets.GetAsset("/schemas/manifest.json") - schemaLoader := gojsonschema.NewStringLoader(manifestSchema) - - appConfigLoader := gojsonschema.NewGoLoader(publishAppConfig) - - result, err := gojsonschema.Validate(schemaLoader, appConfigLoader) - if err != nil { - return err - } - - if !result.Valid() { - var errs []string - for _, resultError := range result.Errors() { - errs = append(errs, resultError.String()+"\n") - } - - return errors.New(fmt.Sprintf("app config invalid: %s", errs)) - } - - if publishAppConfig.Type != AppTypeCustom { - return nil - } - - if len(publishAppConfig.IdentitySpaces) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.IdentitySpaces)) - for _, identitySpace := range publishAppConfig.IdentitySpaces { - if _, ok := codes[identitySpace.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "identitySpaces.code "+identitySpace.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, identitySpace.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "identitySpaces.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[identitySpace.Code] = struct{}{} - } - } - - if len(publishAppConfig.PurposeTemplates) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.PurposeTemplates)) - for _, purposeTemplate := range publishAppConfig.PurposeTemplates { - if _, ok := codes[purposeTemplate.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "purposeTemplates.code "+purposeTemplate.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, purposeTemplate.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "purposeTemplates.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[purposeTemplate.Code] = struct{}{} - } - } - - if len(publishAppConfig.Purposes) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.Purposes)) - for _, purpose := range publishAppConfig.Purposes { - if _, ok := codes[purpose.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "purposes.code "+purpose.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, purpose.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "purposes.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[purpose.Code] = struct{}{} - } - } - - if len(publishAppConfig.PolicyScopes) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.PolicyScopes)) - for _, policyScope := range publishAppConfig.PolicyScopes { - if _, ok := codes[policyScope.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "policyScopes.code "+policyScope.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, policyScope.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "policyScopes.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[policyScope.Code] = struct{}{} - } - } - - if len(publishAppConfig.LegalBases) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.LegalBases)) - for _, legalBasis := range publishAppConfig.LegalBases { - if _, ok := codes[legalBasis.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "legalBases.code "+legalBasis.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, legalBasis.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "legalBases.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[legalBasis.Code] = struct{}{} - } - } - - if len(publishAppConfig.Themes) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.Themes)) - for _, theme := range publishAppConfig.Themes { - if _, ok := codes[theme.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "themes.code "+theme.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, theme.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "themes.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[theme.Code] = struct{}{} - } - } - - if len(publishAppConfig.Rights) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.Rights)) - for _, right := range publishAppConfig.Rights { - if _, ok := codes[right.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "rights.code "+right.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, right.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "right.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[right.Code] = struct{}{} - } - } - - if len(publishAppConfig.Regulations) > 0 { - codes := make(map[string]interface{}, len(publishAppConfig.Regulations)) - for _, regulation := range publishAppConfig.Regulations { - if _, ok := codes[regulation.Code]; ok { - return errors.New(fmt.Sprintf("app config invalid: %s", - "regulations.code "+regulation.Code+" is not unique")) - } - - if !isEntityCodeValid(publishAppConfig.Code, regulation.Code) { - return errors.New(fmt.Sprintf("app config invalid: %s", - "regulation.code must start with \""+publishAppConfig.Code+".\"")) - } - - codes[regulation.Code] = struct{}{} - } - } - - return nil -} - -func isEntityCodeValid(appCode, entityCode string) bool { - if strings.HasPrefix(appCode, entityCode+".") { - return true - } - - return false -} - -func isRemoteLink(link string) bool { - _, err := url.ParseRequestURI(link) - if err != nil { - return false - } - - u, err := url.Parse(link) - if err != nil || u.Scheme == "" || u.Host == "" { - return false - } - - return true -} - -func getFileData(link string) ([]byte, error) { - if isRemoteLink(link) { - return getRemoteFileData(link) - } - - return getLocalFileData(link) -} - -func getRemoteFileData(url string) ([]byte, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - return ioutil.ReadAll(resp.Body) -} - -func getLocalFileData(link string) ([]byte, error) { - if filepath.IsAbs(link) { - return ioutil.ReadFile(link) - } - - return ioutil.ReadFile(link) -} diff --git a/apps/validate.go b/apps/validate.go deleted file mode 100644 index ece8285..0000000 --- a/apps/validate.go +++ /dev/null @@ -1,45 +0,0 @@ -package apps - -import ( - "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/flags" - "gopkg.in/yaml.v3" - "io/ioutil" - "os" - "path/filepath" -) - -func Validate(cmd *cobra.Command, args []string) error { - appConfig, err := cmd.Flags().GetString(flags.File) - if err != nil { - return err - } - - b, err := ioutil.ReadFile(appConfig) - if err != nil { - return err - } - - b = []byte(os.ExpandEnv(string(b))) - - appConfig, err = filepath.Abs(appConfig) - if err != nil { - return err - } - - basePath := filepath.Dir(appConfig) - if err = os.Chdir(basePath); err != nil { - return err - } - - var manifestInputs ManifestInputs - if err := yaml.Unmarshal(b, &manifestInputs); err != nil { - return err - } - - if err := validateAppConfig(manifestInputs); err != nil { - return err - } - - return nil -} diff --git a/assets/assets.go b/assets/assets.go deleted file mode 100644 index db77e4e..0000000 --- a/assets/assets.go +++ /dev/null @@ -1,17 +0,0 @@ -package assets - -import "io/ioutil" - -func GetAsset(url string) string { - f, err := Assets.Open(url) - if err != nil { - return "" - } - - b, err := ioutil.ReadAll(f) - if err != nil { - return "" - } - - return string(b) -} diff --git a/assets/assets_gen.go b/assets/assets_gen.go deleted file mode 100644 index 14ebe42..0000000 --- a/assets/assets_gen.go +++ /dev/null @@ -1,191 +0,0 @@ -// Code generated by vfsgen; DO NOT EDIT. - -package assets - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - pathpkg "path" - "time" -) - -// Assets statically implements the virtual filesystem provided to vfsgen. -var Assets = func() http.FileSystem { - fs := vfsgen۰FS{ - "/": &vfsgen۰DirInfo{ - name: "/", - modTime: time.Date(2021, 4, 30, 16, 42, 37, 829061251, time.UTC), - }, - "/schemas": &vfsgen۰DirInfo{ - name: "schemas", - modTime: time.Date(2021, 4, 30, 16, 42, 51, 47696507, time.UTC), - }, - "/schemas/manifest.json": &vfsgen۰CompressedFileInfo{ - name: "manifest.json", - modTime: time.Date(2021, 4, 30, 16, 42, 51, 47571946, time.UTC), - uncompressedSize: 52818, - - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3d\xed\x8e\xdc\x36\x92\xff\xfd\x14\x44\x23\xc0\xee\x1e\x6c\xe7\xe3\x6e\x73\xd8\x00\xf7\x63\xe2\x38\x88\x73\x5e\xdb\x3b\x33\x4e\x7e\x24\xbe\x06\x5b\x2a\xb5\xe8\xa6\x48\x85\xa4\x7a\xa6\x37\x30\xb0\x0f\x72\xf7\x72\xfb\x24\x07\x92\x52\xb7\x3e\x48\x8a\x52\xf7\x78\x26\xd9\x36\xb0\xd8\x4c\x93\x2c\x16\x8b\xf5\xcd\x22\xf5\xeb\x23\x84\x16\x9f\xc8\x24\x87\x02\x2f\xbe\x42\x8b\x5c\xa9\xf2\xab\x4f\x3f\x7d\x2f\x39\x7b\x62\x7f\x7d\xca\xc5\xfa\xd3\x54\xe0\x4c\x3d\xf9\xec\x3f\x3f\xad\x7b\x3e\xd6\xc3\xd4\xae\x04\x3d\x86\xaf\xde\x43\xa2\xea\xdf\x88\xa2\xe6\xc7\xbf\x62\xb1\x01\x55\x52\x9c\x00\xc2\x65\x89\xda\x03\x05\xfc\x52\x11\x01\xe9\xe2\x2b\xf4\xd3\x23\x84\x10\x5a\x30\x5c\x80\x69\x43\x68\x91\xf0\x14\x16\x8f\x10\x7a\x67\xfa\xa6\x50\x02\x4b\x81\x25\x04\xe4\xe2\x2b\xf4\xab\xed\xa3\x21\x80\x54\x6f\x25\x88\x8b\x4a\xe5\x1a\xd0\xa2\x92\x20\x96\xb8\x52\xf9\x32\xc1\x94\xae\x70\xb2\x59\x56\x82\x2e\xde\x3d\x42\xe8\x83\x01\x85\xd3\x94\x28\xc2\x19\xa6\x6f\x04\x2f\x41\x28\x0b\x32\xc3\x54\x82\xe9\x50\xb6\x7f\xfe\xb5\x85\x4d\xf3\x57\x6b\xd1\x52\x09\xc2\xd6\x35\xce\xed\x85\x5f\x94\x25\x7a\xa6\x07\xed\x9b\x52\xc8\x70\x45\x95\x6e\x5c\x98\xdf\x3e\xd4\x2b\x25\xe9\x64\xc8\x2f\xbe\x89\x80\xcb\xc5\x7a\x12\xe0\xd7\x62\x8d\x19\xf9\x3b\xd6\xc4\x89\x00\x6f\x36\x6b\x2a\xe2\x66\x50\x07\xcc\x16\x84\xd4\x13\x4e\x85\x24\xa1\xc0\x4c\x91\x04\x35\x00\xf6\xdd\x4a\xac\x14\x08\x0d\x71\xf1\x3f\x7f\xfc\xe9\xb3\x27\x7f\x79\xf7\xeb\xe7\x8f\xbf\xfc\xf0\xa7\x9f\x7f\x7e\x1a\xf8\xf3\x93\x2e\x5a\xb8\x52\xfc\x6d\xb9\x16\xd8\xbd\xef\x2b\xce\x29\x60\xe6\xc0\x4d\x82\x42\x8a\x23\x25\x2a\x40\x19\x17\x88\x30\xa9\x30\x4b\x40\xea\x5f\x57\x80\x34\xe0\x02\x2b\xa2\xb9\x73\x87\x2a\x3b\x45\x8a\x6e\x72\x60\x88\xc1\x4d\xb3\x1c\x89\xb0\x00\x54\x56\x2b\x4a\x64\x0e\x69\x17\x39\x2b\x0d\x72\x12\xcd\x12\x5e\x14\xf8\x89\x84\x12\x0b\xac\x20\x45\x94\x48\x85\x78\x86\xf6\x92\xb5\x43\xb5\x40\x16\xc0\x94\x7c\x8c\x3e\x29\x71\xb2\xc1\x6b\x40\x7f\xfc\xa4\xc6\xe9\x4f\x5d\x2c\x4a\xc1\xb7\x24\x05\x27\x1a\x58\x08\xbc\x3b\x60\x41\x14\x14\xed\x7e\x43\x84\xeb\x86\x0f\x43\xc4\x0d\x28\x8d\xe9\xd5\x7f\xbf\xfd\x83\x44\xf5\xac\x29\x5a\xed\x90\xca\x89\x44\x05\x66\x24\x03\xa9\xba\xc8\xd5\xe0\x47\xe9\x03\xac\x2a\xf6\x0a\xc8\xfc\x22\x77\x52\x41\xb1\xef\xa1\xb1\x67\x9a\x9f\x30\x6d\xff\x96\x54\x52\xf1\xa2\x41\xfb\x9d\x4b\x5c\xea\x2e\xc3\x15\x69\x5c\xf4\x82\x54\x0e\xa8\x26\x72\x4f\x23\x34\x3c\x33\x6f\x05\x45\x45\x15\x29\x29\xb4\xf1\x95\x84\xad\x29\x04\xf1\x1d\x0c\x3b\x60\xcc\xaa\x62\x05\x42\xe3\x7c\x60\x67\x4c\x29\xbf\xe9\x73\x66\x29\x48\x81\xc5\xee\x19\x56\xb0\xe6\x62\xe7\xc0\xff\xa7\xfd\x02\x34\x58\x4a\x17\xef\x86\xd3\xb5\xad\x86\x96\xf5\x1a\x2a\x4a\x1a\xb0\x81\xc5\x97\x82\x6c\x71\xb2\x6b\xaf\x1d\x4b\x09\x6a\xbf\xf4\x0e\xbe\x12\x12\xce\xd2\xd3\x63\xbc\x87\x7b\x07\x38\x8b\x8a\x3a\x39\xe3\xa7\xbd\x09\xf6\xe3\xa9\x71\xb3\xe3\xf7\x6d\x63\xf6\xb0\xc6\x70\x60\x13\xcd\xef\x5b\x02\x37\x9d\x5f\xfc\x8c\xda\x45\x44\x23\x81\xe0\xb6\x14\x20\x35\x6b\x5a\xfd\xa7\x05\x42\x7b\x09\x44\xa2\x2d\x91\x64\xd5\x61\x61\x97\x2d\x42\x6d\x95\xd1\x08\x0e\xa5\xc7\x63\xc4\x59\x17\xa3\x04\x33\xad\xbc\x6b\xf8\x90\xc6\xe0\xf5\xa8\xfd\xff\xcd\xe6\x25\xb8\xc4\x2b\x42\x49\x8f\x94\x3e\xc5\xd9\xd9\xb8\xce\xd8\x09\xba\xb5\x45\x20\x37\xbc\x0e\xe7\x0d\xd8\x53\x6f\x3f\x88\x82\x28\xcd\x1f\x78\xdd\xf5\x0f\x5a\xcd\x2f\xd8\x1a\xe4\xb0\x51\x90\x75\xee\x1f\x6a\x5a\x3d\x23\x15\x5e\xbf\x16\x49\x0e\x52\x09\x3b\x72\xdf\xf8\xce\x49\x5b\x59\x95\x25\x17\x0a\xd2\x97\x98\xad\x2b\xbc\xf6\x48\x49\x4d\xe2\xb0\x90\xec\x61\x21\xba\x07\x36\x8f\xe4\x2e\x7a\x42\xfc\x5a\xde\x54\xa2\xe4\xf2\x98\xa5\x94\x0d\x84\x13\xe2\x2f\x25\x30\x45\x30\x5d\x4a\x10\x5b\x92\xb4\x80\xa3\x5a\x5d\xa4\x4b\x60\xb9\xb6\x14\xda\x9d\xe8\xb6\x62\x86\xe9\x4e\x91\xa4\x37\x68\x05\x39\xde\x12\x2e\x30\x5d\xe2\x74\xab\xb5\x8d\x1c\x48\x6b\x09\x42\x6a\x55\xd5\x77\x53\xed\x1a\x80\xc2\xb2\xd8\xa8\xde\x18\x59\x48\xc7\xaf\x50\x60\x42\x1d\xbf\x7b\x7e\x4e\xb1\xc2\xcb\x95\xe0\x9b\x96\xb3\x32\xba\x77\x97\x9a\xb9\x8f\xd8\x39\x61\xc7\x9f\x6e\xdf\x52\xa0\xa0\x7a\x4a\x15\x27\x09\xc8\xde\x56\x24\x5c\x08\x48\x1c\x82\xce\x85\x6a\x54\xc6\x18\x11\x72\x2e\xd4\x37\x20\x13\x41\x4a\x35\xd5\xc1\x37\x83\x51\x7a\x18\x8d\x54\x8e\x95\xd6\xc4\x80\x85\x44\x84\x21\x09\x58\x24\x39\x12\x20\x2b\xaa\x24\xc2\x2c\x45\x6b\xad\x99\x45\x47\x37\x7a\x83\x97\x14\x14\x26\x14\xd2\xb9\x08\x36\xe3\xfd\x38\xf2\x83\xf1\xb0\x9d\x25\x92\x89\x00\x88\x09\xad\x8c\x3e\x35\x56\xe8\x15\x57\xd3\x83\xac\xc3\x70\xc4\xb8\x02\x24\x73\x7e\xc3\x4c\x50\x92\x03\xd2\xf1\xb1\xb5\x6d\x58\x6a\x66\x36\x41\x8a\x8e\x97\xb9\x88\x8f\xfd\x0e\x33\x1c\xa3\x97\x5a\x40\x8e\xb4\x66\x6f\xf6\xa0\x16\x4e\x66\x24\x2c\xe3\x6f\x2f\x5f\x4e\xa6\xa4\x1e\x87\xf4\xc0\x9e\xd3\xa8\xaa\x72\x0e\x38\x33\x70\x08\x2f\xe7\x05\x94\x78\x0d\x73\x40\x36\x63\x87\x50\x6d\xf8\x01\xe2\xca\x6a\xa3\x39\xc0\x1b\x10\x8d\x35\x1c\x4e\x52\x7b\xae\x6f\x38\x25\xc9\x6e\xce\x14\x35\x00\x54\x1a\x08\x0e\x5a\x2b\xac\x2a\x39\x8b\xd8\x66\xe4\x10\xa2\xe2\xb3\xc0\x29\x10\x85\xd4\x11\x50\x6d\xf1\x86\x80\x53\x9e\xcc\x01\x9c\xf2\xa4\xd2\x36\xd2\xc8\xde\x10\x2a\xe5\x6b\x3e\xd3\xd9\xef\x07\x25\x06\xd4\xbe\xdb\x20\xfd\x66\xa7\x23\x6c\x33\x8c\x12\xa3\x62\x84\x26\x93\xa0\x2e\x0f\x90\x5b\x62\x7c\x43\xd2\x3a\x45\x97\x83\xb6\x6b\x07\x8c\xb5\x08\xd8\x9f\x74\xab\xed\xb7\x37\x2a\xa3\x21\x48\xb3\xdc\xe9\x1e\xbf\xa6\x07\xb2\x7f\x4d\x0b\x33\x0c\x91\xe6\xcc\x98\x11\x0a\x87\x14\x58\x1f\x6c\x43\x21\x27\x5c\xc2\x14\xac\x41\x84\x96\x62\xc7\x7b\x96\xf2\x99\x73\xca\x3d\xdd\xe7\xce\x59\x03\x18\x9f\xd4\xa9\x97\x4b\x01\x3a\x82\x9c\x69\x44\x86\x69\x82\x1a\x5a\x8c\x35\x69\xa5\xab\xfb\x70\x5f\x14\x78\xdd\x49\x9e\x38\x45\xa5\x27\x2c\x2d\x71\x89\x14\x98\x51\x91\x19\x11\x9a\x90\xd8\x74\x77\xd9\x23\x3a\x1e\xe1\x09\x33\xf3\x80\x50\x0e\x09\xf2\xc9\x50\x07\x2b\xb7\x1c\x4d\x9d\x7c\x28\x51\xfd\x49\x5c\x52\x35\xc2\xe3\xc3\x69\x86\xa2\xe5\xe1\xf3\xfe\xec\x4e\x01\x9b\x3c\xbd\x43\xca\xfc\xf3\x8f\xc8\x5c\xc2\x99\xc2\xc9\x31\x61\xc9\x1e\xc2\x3c\x39\xf3\x49\x93\x19\x31\x8c\xd1\x8e\x12\xb0\x00\xe7\x77\x13\xc4\x3d\xac\x47\x78\xaf\x45\x05\x34\x40\xdb\x1d\x7b\x59\x00\x90\xe4\x8c\x24\x9d\x54\x72\xdd\x54\x18\x65\x36\x9c\x14\x69\xab\xc1\x74\x20\x3d\x6c\x90\x90\x54\xa2\x13\x8b\xa1\x56\x3c\x86\x06\xcc\x68\xe9\x79\x8a\x45\x5b\x48\xbd\x9e\x19\x17\x05\x36\x22\xdf\xdb\xb8\x71\xa6\x84\xdb\x92\x08\x78\x2b\x41\x5c\xf3\x0d\x38\xa3\x8a\xc0\x99\xcb\x73\x33\xda\x86\x36\xca\x8e\x77\xc4\x30\x86\x37\x3a\xb3\x0a\xc8\x04\xc8\xfc\x05\x53\x20\xb6\x98\x4e\x76\xdd\xea\xf1\x88\x34\x00\x0e\xce\xca\xe1\x0c\xea\x8f\x3f\x7d\xfe\xe4\x2f\xef\xcc\x49\xd3\xbf\xfd\x29\x8f\x08\xae\x86\xa7\x9a\x13\x48\x71\x69\x07\x5b\x5a\xe8\xb0\x2e\x8e\x12\x55\x3d\xd9\xb3\xfa\xcc\x34\xd2\x91\x3d\xec\x78\x25\x88\x87\x48\xaf\x35\x5c\xd4\x1c\xc6\x1a\x07\x37\x86\x06\x29\x11\x90\xa8\xd7\xec\x6d\x99\x62\x77\x0c\x1c\x22\x82\x1d\xad\x83\xf0\xca\x8e\x8f\xa2\xc2\x0d\xac\x72\xce\x37\x47\xe4\xd6\x1b\x08\x23\x5e\x76\x25\x3a\x87\x49\xb0\x05\xa6\xe4\x4c\xb7\xdb\xe7\x17\xeb\x39\x26\xf8\xa8\xee\xad\xec\xae\xf0\x47\xbb\x3a\xf4\xf6\xf2\x85\xdb\x83\x95\x90\x08\xf0\xba\x93\x41\xd7\xf8\x6b\x2c\xe1\xcb\xff\x78\x02\x2c\xe1\xe6\x3c\xb4\x9e\xca\x42\xd4\xec\x9c\x22\xc5\x91\x24\x6b\x86\x6a\x72\xf5\x32\x56\x4c\x01\x53\xcf\xf5\x70\x3d\x89\xe6\x0f\x03\x71\xa2\x6b\xdf\xcd\x84\xcc\x59\x48\x43\xa4\x0e\x24\x94\x03\x4e\x41\xec\xd7\xa1\x1b\x81\x29\x92\x60\x05\x4d\x66\xa6\xcf\x3b\x71\x08\xd7\xc4\x70\x63\xea\x35\xe8\x6e\x94\x5d\x84\x1d\x9a\xf6\x31\x52\x04\xec\x5f\xe9\xb4\x6f\xf5\x19\xc0\x96\x27\x86\x56\x4f\x13\x01\x58\xf5\xce\x58\x9c\x1d\xb3\x8a\x66\x64\x70\x1c\x63\xf7\xb1\x2c\x9f\xba\x4f\x6b\xf6\xcd\xb5\xf6\x76\x37\x56\x2c\x30\x3a\xe1\x4c\x02\x53\x4f\xcb\xfa\x54\xc3\xd5\x47\xe1\xf5\x53\x9c\x28\xb2\xc5\xca\x61\xb9\x75\x6b\x0a\xe1\xf6\xda\x0e\xbc\x24\x52\x05\x0c\xbc\x93\x29\x0a\x7c\xfb\xb7\x37\x57\x93\xc2\xba\x83\xfc\x13\xa6\xfe\xfd\x0b\x1f\x17\x7e\xfe\x99\x3b\x90\x54\xd4\xcf\x83\x3e\xd5\x89\x3a\x4c\x78\xfd\xf2\x4a\xbb\x17\x19\x59\x57\xc2\x75\xc6\xe4\xf3\xe4\xec\xb1\x9f\xf6\x84\x86\xfe\x9c\xc3\x5a\x74\xda\x3f\x4c\x70\x51\x34\x81\x26\xf9\xcc\x27\x71\x8a\x5b\x25\x51\x6d\x18\x77\xe3\x13\xf7\x4a\x7a\x7a\x48\xbb\x45\x3d\xed\x64\xd0\x17\xd7\x39\xa0\x0d\xec\x50\x46\x80\xa6\x88\x48\x74\x93\x83\x00\xa3\xdf\x52\xac\x30\xba\x21\x94\xa2\x15\x20\x89\xb7\x46\x13\x3e\x45\xd7\xa6\x88\xa3\x92\x4a\xff\x5c\x31\xf2\x4b\x05\xa8\x04\x61\x21\x3c\xfd\x99\xa1\x6f\xb9\x40\x70\x8b\x8b\x92\xc2\x63\x44\x32\x03\xfe\xbf\xd0\x1f\x9a\xe4\xa4\xfc\x83\x86\x6e\xb3\xed\x5b\x4c\xab\x7d\x69\x85\x45\xa1\x3b\x21\x61\x06\x8d\xa7\xfb\xc1\xfe\xb8\x71\x56\x68\xec\xa0\x86\x26\x2a\xe2\xc2\x86\xc9\x26\xdb\x6e\xca\x56\x12\x5e\x94\x9c\x01\x53\x01\x0c\x66\x84\x28\x0e\x04\x4c\xb9\x49\xbd\xe9\xbb\x3d\x3d\xf6\x16\x15\xa8\xf6\x94\x6e\x72\x92\xe4\x07\xa4\x74\x8b\x00\xa6\x4d\x56\x7d\x90\x91\x09\x63\x61\xd3\xa7\xe8\x85\x42\x09\x66\x8c\x9b\x0d\xc3\x0c\xc1\x2d\x91\xca\x9c\x24\x18\x82\x4f\x89\x87\xba\xa7\xdd\xfb\x9f\xbb\x35\x41\xf6\x9f\x3f\xaa\x91\x39\xbf\x79\xcd\x7e\x18\x56\x22\x04\x7c\x45\x37\xb5\x5e\x64\xa6\x6e\xeb\x71\x9f\x7d\xec\x99\x4e\x43\x89\x84\x33\x66\x0f\xc7\x10\xdf\x82\x30\x25\x10\xde\xc8\xfc\xe0\x64\xfa\x50\xff\x41\xf3\xec\x6b\xf6\x3c\x25\x81\x34\x41\x34\xfe\x56\xd8\x5b\x0b\xb0\x22\x61\x96\x51\x6f\x99\x3d\x0e\xaa\x17\x03\x29\x51\xfd\x83\xa9\xc1\x22\x34\x51\xbc\x6b\xd0\x10\xf0\x2a\x24\x2a\xf3\x91\x3f\xf0\x59\x92\x63\xb6\x1e\xd8\xd9\x58\x1c\x85\x3b\xbd\x76\x32\x06\x59\x41\x53\x3c\x67\x64\x2a\xc7\x5b\x40\xd8\x92\xde\x2f\xde\x05\x61\x2f\x81\xad\x67\x24\xa7\x3a\xb6\xba\xe7\xe2\x46\xe6\xa5\x0a\x7c\x7b\x7f\x93\x1f\xa2\xe3\x89\xba\x2d\x22\xa7\x68\xd2\xc1\x39\xa7\x29\x88\x13\xe8\xce\x16\x34\xa4\xe0\x56\xd9\x33\xde\xb6\x52\xa8\xcb\x84\x88\x3c\x98\x3c\x28\x4a\xd5\xd7\x6a\x71\xc8\x1f\x3a\xb9\x11\xf7\x97\xa2\xb9\x97\xf0\x8d\x85\xd7\x56\x02\x2b\x68\x59\xca\xbd\x35\x32\xb8\x3f\x46\x2b\xc8\x78\x93\x48\x31\x49\x0d\x6c\xf4\xdc\x53\xf4\x1d\xde\x6a\x0d\x8f\x51\x3a\x84\xa8\x95\xa0\x20\xa9\x85\xdb\x27\x98\x7f\xad\xb2\x04\x4a\x93\x1c\x92\x40\x0a\x38\x4e\x2a\x8d\x07\x21\x41\x19\x23\x64\x50\x02\xa6\x35\x12\x32\x53\x20\x33\xc7\xde\x8c\x19\xaf\x62\xa6\x1a\xd9\x57\x48\x9e\x4a\x8d\x34\x00\x2d\x39\x65\x53\x66\x86\xd3\xd4\xfa\x2a\x87\xbd\xd1\x8e\xd0\x75\xbe\xef\xd8\xe6\x40\x2c\xb5\x15\xb6\x65\xb2\xc4\xae\xf2\xe2\xcd\x0b\x53\x12\x81\x19\xfa\xe7\x3f\xfe\xf7\x22\x4d\xd1\x05\xe3\x2a\x07\xf1\xcf\x7f\xfc\x1f\x5a\x55\x4a\x71\xb6\xe7\x86\xba\xd2\xae\x43\x20\x5b\xdc\xa9\xc9\x69\x0c\x9e\x8e\xc7\x8c\xb9\xcb\xd0\xc1\xc7\xb4\x3d\xa5\xcb\xa3\x99\x69\x0d\xb5\x67\xe6\x27\xed\xc0\x67\x46\x23\x61\x01\x42\x0b\xce\xe0\x75\xe6\x68\x40\x68\x61\x09\xe9\x6c\x8b\x8c\x9f\x7d\xbb\x7b\x9d\x83\x04\x53\xbe\xad\x0e\x1b\x76\xd0\x1b\xda\x02\x1b\x9f\x0b\x52\x4b\xf3\x66\x8b\x07\x7e\x10\xf2\xc7\xdf\x71\xd4\xd9\xf7\xf2\x44\x17\x9d\x3e\x14\xaf\x60\x98\x97\xee\xd2\x6b\xe1\x6c\x75\x52\x25\x3a\x1e\xe9\x0c\x09\x6e\x67\x0f\x17\x7f\x87\xa1\xa6\xf7\x74\xfc\xe0\x5d\xae\xa5\xc6\x29\xa6\x70\xfe\xee\xfa\x75\xf8\x9b\x03\xbd\xc5\x7b\x39\xc8\x4b\xf9\x30\x8a\x61\xd6\xe7\x5a\xcb\x23\x8c\xbe\xbf\x7a\xfd\x0a\x5d\x18\x1d\xa2\xb8\x36\x00\xc6\xcf\x97\x39\xaf\x68\xaa\x59\xd6\x5a\x7d\xcd\xb3\x6d\x75\xc3\x33\x64\x19\x4f\x6b\x24\x95\x9b\x58\x27\x45\xad\x4d\xf4\xa0\xe0\x34\x85\xfe\x35\x0f\x53\x99\xa7\x58\x72\x25\xa8\xc5\x1a\xdb\xd0\x54\xf2\x4a\x24\xa0\x55\x68\x8b\x18\x76\xdd\x75\x94\x5a\xab\xe7\x26\x74\x2a\x79\x59\x51\xac\xb4\xab\x77\x65\xa3\x28\x73\xa9\xc2\xc0\x84\x5b\x7b\x67\xc0\xc2\xaa\x95\x8d\x13\x3b\x7f\xe2\x35\x92\x60\x8f\x42\x7f\x4f\xc9\x70\x90\x14\x98\x22\x6a\x77\x55\x62\xf7\xdd\x83\xc8\xf3\xc1\x06\x0e\x92\x16\xd0\xbc\x8c\x48\x00\x64\xbb\x5b\xa3\xe2\xdb\x7a\xad\x67\x41\x02\xda\xcf\x5e\xec\x1a\x04\xa0\x83\xac\x8b\xf9\x35\x23\x54\xf5\x52\x06\x03\xe5\x37\x62\x90\x0a\xcc\xf0\xda\x11\x87\xa0\x71\x27\xa2\x4b\x94\x1f\x73\xd0\xf6\xdc\x9a\x8f\x2e\x75\x90\xbd\x14\xa3\xe7\x41\x5c\xa0\x42\xbb\x09\x2e\xe3\xd2\x3e\xa4\x32\x3a\xb9\xcf\x5b\x03\x51\xec\x5f\x83\x73\xe0\xee\x95\xc3\xd0\x7e\xa2\xe6\xb2\x5f\x78\x76\x67\x7a\xea\x04\xb3\xf7\xeb\x07\xdc\xb3\xa7\xce\x52\xd1\x93\x21\xd1\x06\xef\x18\x1a\x50\x01\x43\x54\x1b\x46\x0d\xa2\xe9\xce\xbd\x8c\x60\xd9\x40\x76\x0c\x0b\x39\x2a\x31\x6e\x4a\x6b\xde\x7a\x1a\x77\xb7\x51\x5f\x66\x58\x48\xd0\x26\x8d\xd5\xb6\x8e\x46\xb7\x6f\x37\xd5\x87\x89\xf1\x60\xdc\x89\xbd\x61\x7b\xc8\xa8\xa1\xb8\x9d\x72\x65\xe3\x5a\x00\x3c\x79\xb9\x76\x0f\xc7\x41\x7f\xa7\x43\xc2\x99\x12\x9c\x52\x10\xcb\x26\xa9\xba\x24\x6e\x5f\xb6\x1e\x81\x59\x2a\x38\x49\xdb\x45\xfe\x91\x23\xc2\xbd\x32\x22\x60\x02\x50\xc2\xe5\xc4\xde\x5b\x60\x29\x1f\x5b\x5d\x41\x12\xc1\x25\xcf\xd4\x04\xe0\x87\x31\xcd\x85\xcf\xb1\x59\x04\xdf\x54\xd3\x3a\xc7\x63\x63\x73\xf0\xcb\x95\xe0\x37\xd2\x23\x84\x75\x4f\x05\x14\xca\x9c\x33\x4f\x5c\xd0\x4d\xda\x1e\xfe\x79\xbc\xee\x83\x27\xf4\x31\x04\xa3\x9e\xec\x08\xd1\x10\xb8\x9f\xf7\xed\x34\x5f\x7d\x77\xf1\xf9\x48\xfb\x17\x7f\xfe\x72\xa4\xc7\x9f\x3f\xff\x62\x22\x6d\xe3\x02\x8b\x78\x9f\xf1\xf1\xdd\xfb\x55\x4e\x1d\xb5\xd8\x62\x41\x4c\x5e\xf9\x77\xe8\x6e\x29\x31\x8c\xa5\xcf\xde\x56\x1b\xc2\x6f\xc8\xdb\xf2\x5a\xf3\x23\x71\x0c\x5b\xf0\x90\x82\x0a\x58\xed\x29\xf6\x7a\x8a\xa5\x1e\xb3\xd1\xd1\xd6\x39\xd6\x2e\x47\x58\xe4\x69\xb6\x78\x8a\x15\x8e\xb4\xbf\xd1\x96\x37\xc6\xe6\x86\xac\x6d\xdf\x16\x38\x42\x02\xbf\x6d\x3d\x0d\x9b\x7a\xed\x69\x5b\x98\xdc\x26\x33\xc8\xca\x3e\x2b\xbb\x90\x39\x76\xdb\x57\xdd\xe2\xb3\xac\xba\xcd\x69\x53\xc7\x29\xb8\xb7\x47\x41\x1a\x7a\x03\x9c\x03\x0d\x7f\xa8\x01\xa1\x14\x32\xc2\x88\x4f\x07\x8d\xc4\x39\x0b\x5a\x57\x41\xb9\xd7\xe9\xd2\xb2\xce\x18\x67\x62\x84\x33\x1e\xdf\xf8\x0d\x07\x8a\x76\xe1\x0e\xc4\x7a\x65\xaa\x27\xb2\x3a\x95\xee\xf2\x08\xec\x3f\xa7\x4f\x79\xa0\xd1\xa9\xd0\x79\x59\x03\x1c\xa0\xe4\x19\x38\xe2\x45\x2e\x6e\x08\x4b\xb9\xdf\x8d\x5c\x24\x9c\x6f\x48\x20\x80\x4b\xb1\xc2\x2f\xf1\x0e\x84\x27\x33\x1f\x4d\xa9\xf7\x37\x7e\xc7\x3b\xae\x92\xab\xdd\xbf\x21\xd7\xf7\x3f\x5e\x37\xb7\x5f\x8f\x3a\x9a\x08\xb1\xba\xe9\xb1\x81\xdd\x03\x39\x9b\x18\x65\x39\x34\x21\x90\xe9\x5e\xb7\xaa\x59\x4f\x71\x94\x11\x96\x76\xf8\xcf\x24\x9d\xeb\xc3\xbf\xef\x7f\xbc\x0e\x01\x1c\x0d\x6c\xcc\xad\x15\x9c\x06\x43\x3f\xcd\x9a\x14\x93\x42\xfa\xa2\x13\x5f\x7c\x12\x3a\x73\xd1\x9b\x78\x6a\xaa\x6d\x60\xd7\x97\xd5\x3e\xad\x7c\x78\x7e\x9c\xf8\x6a\xff\xdf\xee\x6b\xf4\x37\x5c\x6c\x32\xca\xe7\x5e\x91\x3b\x98\x18\x4d\x85\x03\xb0\x79\x29\x79\x7f\xe5\xa0\x33\x54\x89\xbd\x58\xa2\x07\x37\x9b\xd4\xa0\xe8\xaf\x1b\x98\x53\xa4\x78\x78\xc8\xa8\x65\x4e\xc6\xa7\x12\x80\x53\xce\xe8\x90\x2b\xc7\xce\xfb\xbb\xaf\x81\x89\xca\xd4\x78\x17\x78\x03\x9d\x89\x4d\x41\xd6\xbe\x7c\xaa\x07\xa2\xe5\x35\x0d\x92\xf3\x5d\x2c\xb9\x09\x63\x02\x35\xda\xee\x93\xf3\x3d\x8e\xf5\x78\x73\x90\x2f\x15\x16\xaa\x39\xf7\xdf\x13\x68\x52\xcc\xad\xb0\xdc\xfc\xad\x02\xcf\x01\xed\xc8\xa9\xe9\xd0\xed\x6a\x90\x78\x7e\x0b\x49\xa5\x11\xbd\x26\x05\xf0\x6a\xc4\x95\x75\xd7\x2e\x21\xe4\xa8\x5f\x8a\xc6\xe0\xb2\xba\xbf\xb9\xaf\xb1\xdc\x7c\xf4\xc9\x0b\x28\xf8\x5c\x6f\xd7\x63\x5f\x63\xce\x70\xc7\xb5\xe9\x00\x53\xfb\x1a\xc8\x85\x52\x82\xac\x2a\xe5\x99\xe9\xc1\x61\x2d\x40\x89\xfa\xe9\x84\xb9\x08\x8f\x7b\xe3\x46\xfd\x63\xea\xb8\xe3\xe6\x99\xcc\xcf\x41\x28\x82\x8b\x9c\x2b\x35\x03\x57\x38\xd9\xf0\x2c\x7b\xc6\x21\xcb\x48\x42\x80\x8d\x3b\x9c\xf1\xb8\xa4\xbc\x9a\x14\x18\x14\xf8\x96\x14\x55\x71\xff\x54\xa9\x11\xb9\x50\x0a\x8a\x72\x70\x8f\xe7\x23\x22\xc2\x38\xbb\xd4\xfc\xa8\x6d\xd1\x73\x21\xb8\xb8\x04\x2c\x5d\x66\x65\x80\x91\xef\x20\x11\xb9\xfd\x0b\x0f\x94\x50\x15\xcd\x9d\x26\xb5\x17\x52\x41\x19\xb0\x9e\xae\xe5\x79\x97\x35\x26\xb2\x2d\xcf\x40\x41\x89\x04\x94\x02\x24\x30\x25\x11\x46\xe6\x17\xc2\x10\xde\x1b\xde\x7e\x9d\xe2\xb8\xc0\x2f\xcc\x95\x22\xa2\x7c\x8e\x74\xd4\x41\x6c\xcc\x11\x26\x71\x27\xd5\x7b\xb3\x04\x37\xd5\xc3\x31\xde\xac\xf7\x09\x60\x8f\x65\x95\x4f\x30\x85\xde\xc5\xbb\x82\x9d\xdd\x19\xd6\x0c\x6e\xa7\x1c\xbc\x4d\x82\xed\xf3\x4f\x1d\xe0\x83\x55\x8c\xb1\x21\xf8\xa8\x0f\x3a\x71\x5d\x81\xb5\x19\x18\x32\xc9\x21\xad\x28\x5c\xf3\x67\x94\x4b\x08\xb9\x69\x8e\x99\xc3\xfa\xbc\xee\x1c\xa1\xd5\xa7\xe0\x79\xa5\xbd\xfc\x87\x8b\xa7\xc1\xee\x81\x13\x33\x07\x2c\xd4\x0a\xf0\xc3\x25\xe3\x0d\x26\xea\x5b\x2e\x9e\x61\x96\x00\xa5\xe3\x39\xa9\xb1\xbb\x92\xb1\xf3\x8e\x79\xb5\x8e\xf9\x46\xf3\x39\x71\x69\x2b\x73\x46\x22\x0a\xc2\x5c\x57\x6a\x07\x58\x9a\xcb\xb5\x96\x3a\x63\x9d\xf1\x0a\xb3\x94\x07\xe8\xe1\xcf\x76\xf9\xf2\x48\xde\xfc\x92\x2f\xf9\x88\x05\x8e\x73\xa4\xc6\x74\xa8\x27\xc6\xe9\x5d\x7c\x08\xe3\x19\x57\xaa\x9c\xe4\x84\xa6\x3f\x36\x49\x84\xb3\x43\xe2\x18\x7b\x76\x48\xce\x0e\xc9\xe4\x75\x05\xd6\x86\x26\xa7\xcc\x1c\x73\x7f\x44\x1b\x15\x97\x5a\x7b\x10\x38\x8e\xa5\xe0\xee\x17\xc9\x7b\x32\xf6\x25\x16\xc0\x94\x71\xd5\xce\x26\x7f\xff\x2f\x44\x31\x6f\x52\xb5\xd5\x27\x52\xfb\xa0\x39\xe6\x7c\x0c\xbf\xa8\x54\xea\x03\xc1\x75\x86\xab\x19\x83\x66\xa4\x52\x47\x53\xd2\xab\x0e\x54\x62\xb4\x03\x9a\xa4\x21\x50\x98\x5e\x68\x62\x1a\xd6\x81\xb3\xfd\x10\xc8\x14\x94\xfd\x99\xd9\x78\x9c\x63\xb3\xb5\x0e\x84\xef\x87\xc8\xb1\x59\xdd\x07\x83\xf0\xe4\xec\xaf\x03\xf3\x50\x1e\xb8\xd5\x7d\x2c\x23\xec\x80\x3c\xe6\x0c\xd9\x7f\xbe\x40\x6b\xbc\xd5\xdf\xf6\xaf\x1b\xbc\xad\xb1\x82\x1b\x7c\xce\x23\x3b\xc7\x7e\x84\xb0\xad\x98\x86\xbe\x97\x63\xc6\xef\x31\xc8\x92\x92\x90\x45\x5c\xbc\xe7\xc4\x5f\x7a\x75\xf8\xb6\x54\xc8\xe9\xa9\xa8\x22\xa7\xb9\x24\x12\x1b\x18\x86\xb5\x51\x84\x16\x8a\x77\x19\xe2\x1d\x86\x30\xbb\xf7\xe6\x1d\xd7\x7a\x41\xad\x1e\xae\xc3\x3c\xf9\x6c\xc1\xf2\xd8\x3b\x99\x51\xd3\x1c\x2b\x3e\x7c\xe6\xe5\x6e\x67\x64\xa7\xdd\xc2\x53\x99\x9e\xd9\x8a\xde\xa4\xdb\xcf\x6a\xde\x35\xf6\x23\xa8\xf9\xbb\xcc\x73\xfd\x16\xdd\x8e\x8c\x30\x22\x87\x8f\x52\xc5\xe3\x7b\x66\xc7\xdf\x35\xcb\x3c\x0a\xfd\x3d\xe5\xb1\x8b\xba\x50\xc2\xfd\x19\xbe\xc9\x95\xb5\x4d\xd9\x45\xf3\x1c\xca\xcc\x02\x5b\xdf\x2b\xa0\x83\xdb\x94\x8e\x77\x41\x49\xd2\x7f\x32\x35\x63\x77\xf4\x4e\xe8\x51\xd5\xbe\x79\x55\x60\xf6\x44\x00\x4e\x4d\x31\xb6\xbd\x4d\x94\x11\x7b\x85\xc8\xd4\x9d\xd6\x74\x69\x6f\xe6\x70\xed\xa7\xa8\x00\xbe\x68\x76\x0d\xcb\xe1\x47\xb2\xfc\xf3\x1b\x4a\xcf\x9d\xbf\xf9\x60\x45\x83\x83\x06\x66\xde\xe1\xcc\x43\x95\xc8\x8e\x83\x96\xd8\x09\xcd\xa3\x5e\x15\x4b\x9a\xbb\x03\x2b\x40\x60\x0e\x06\x9a\x6f\xb7\xba\xe6\x1b\xab\x29\x1e\xbb\x0a\xd2\x9d\xbe\x5d\x61\xdc\x29\x80\x76\x57\x26\xc7\xdf\xcd\x88\x28\x45\x5e\xfe\x12\x5d\x8b\xec\x30\x47\x93\x2e\x82\x36\xcb\x5a\x42\x73\xf0\xb2\x54\x27\xae\xd9\x0d\xa2\xf8\x59\x3c\x86\xa2\x7a\xb8\xb8\x99\x5d\x7b\x68\xc8\x61\xa2\x96\x19\x17\xcb\x64\xec\x84\x25\xe6\x5a\xb9\xff\x41\x3c\xf7\xec\x4d\xe5\xce\x52\xf1\x65\x42\xb9\x84\x87\x46\x9e\x36\x82\x26\x9e\x78\x70\x08\x5a\xa4\x1e\x28\xf9\xf6\xc5\x44\xf7\x8c\x98\xdf\x99\xea\x18\x07\x8f\x93\x38\xea\x3c\x35\xdd\x1a\xd3\x60\xe0\x80\xe3\x3d\xa1\xf9\xe5\xb5\xc1\xdb\x84\xee\x47\x29\x7c\xcf\x52\x34\xb3\xf5\x7e\x1e\x5c\x28\x9c\x74\x95\x70\xb4\x7e\x37\x10\x3f\xc4\xa4\xfc\xbc\x6e\x56\xfd\xb0\x7a\xcb\xdb\xda\x7f\x80\xbe\xde\x84\xb8\xa7\xf8\x02\x49\xa5\x69\xf8\x69\x17\xeb\x49\x26\x08\xb0\x94\xee\x50\xdb\x23\x9a\x88\x51\xe0\x31\xa5\x69\x18\xa9\xce\x67\xf9\x27\xe1\xe0\x7b\xb7\x77\x0e\x1a\xdd\x17\x76\x23\xf0\x99\x29\xc5\xbc\x52\x65\xe5\x38\x9b\x9a\x2c\xc6\x16\x90\xfb\x8d\xc3\xb3\x24\x7f\x3c\x49\xb6\xfb\xf0\x60\xc4\x78\x0a\x3a\x77\x22\xc3\x53\x10\xb8\x73\x01\xf6\x22\x33\x53\x7a\xed\x97\x52\xa6\xde\xf9\x8c\x4b\xca\x8c\x7e\x41\xb0\x5d\xd7\x79\x92\xf4\x89\x81\xd8\x0f\x0b\xcf\x49\x94\x73\x12\xc5\x33\xff\x39\x89\x72\x4e\xa2\xf4\xa6\x3f\x27\x51\xce\x49\x94\xe0\xec\xe7\x24\xca\x39\x89\x72\x4e\xa2\x9c\x43\xaf\x73\x12\xe5\x9c\x44\x39\x59\x18\x76\x4e\xa2\xfc\xce\x24\xf9\x9c\x44\x39\x27\x51\x3e\x4a\x12\xa5\xac\x44\xc9\xa5\xb3\xfa\xa4\x57\xbb\xfa\x51\xdf\x68\xf3\xd2\x2a\x2a\x5f\xe0\x1d\x1d\x2a\x5d\x8a\x06\xa2\x92\xec\x45\xe0\x13\x8e\x8d\x47\x17\x1a\x7f\xed\x92\x91\x91\x24\x80\xf7\x63\xd6\x76\x07\x87\x5a\x57\x96\x90\x10\x4c\xdf\xf8\xda\x33\xc0\xaa\x12\xfe\x81\xdf\xd6\xed\x9d\x66\xff\xf7\x4f\x8f\xf8\x00\x67\xdc\x77\xd9\x8e\xf8\x7a\x66\xdc\x04\x14\xd6\x98\x7e\x8d\x25\x91\x97\xa0\xf7\x20\x09\xf3\xc9\xbc\x17\x79\x5c\xe5\x70\x7e\xd5\x90\x12\x59\x52\xbc\x7b\x75\x1c\xd7\x5b\x20\xdf\x9c\x82\xf9\x4b\xc1\x13\x90\x92\xb0\x75\xc3\x57\xb3\x41\x1d\xc8\x7d\x22\xd5\x77\x22\x9a\xdb\xc7\x6e\x4f\xfe\x14\xd3\x44\x24\x30\xe3\x8c\x24\x7b\xf1\xbd\x2b\x74\x06\xc2\xef\xbd\xa8\xb1\x00\x29\xb5\x9b\x82\xe9\x52\x82\xd8\x92\xc4\xf9\x25\x31\xcd\x20\xe9\x12\x58\x8e\x59\x02\xc5\xf0\x2b\x8c\xa6\x0f\x66\x98\xee\x14\x49\x9c\x00\x56\x90\xe3\x2d\xe1\x02\xd3\xf6\x93\xe5\xce\xa9\x40\x48\xcd\x04\xe4\xef\xbe\x67\x79\xcd\x63\xe5\xcb\x62\xa3\x9c\xe3\x65\x21\xbd\x6d\xe6\xe9\x7a\x6f\x6b\xb0\x31\xc5\x0a\x2f\x57\x82\x6f\x1c\x65\xaf\xef\x22\xb7\x5f\x09\xcc\xa4\xcd\x4c\x4d\x96\x8e\xd9\x6e\x7a\x6c\xad\x6c\x40\x5d\x61\x85\xaf\x2a\x03\xfe\x92\x4f\xff\x6c\xb9\xcf\xc4\x35\x5f\x08\x70\x70\x6b\x51\x52\xbe\x83\x68\x23\xa5\x11\x3c\x25\x66\xb5\x3a\xe4\x0e\xd4\x0e\x5f\x38\x18\xb6\xbd\xe7\x84\xa9\x67\x63\x1d\xde\x84\x80\xb7\x46\xfb\xd7\x1e\xe7\xfc\x5d\x6b\x2a\x62\x75\x76\x02\xcf\x4e\xe0\x60\xe0\xd9\x09\x1c\xd1\xc1\xff\x92\x5e\xe0\xd9\x75\x3b\xbb\x6e\x67\xd7\x6d\xff\xdf\x67\xd7\xed\xec\xba\x75\x3b\x1c\xef\xba\xf5\xf4\x1a\xa5\x70\x4f\x96\x68\xc4\x87\x1c\xb5\x97\x0f\xda\x93\x14\xb0\xae\x3c\x05\x00\x93\x8d\xe1\x3d\xd8\x9d\x91\xbd\x29\xcd\x9b\x44\x57\x09\x2f\xcf\xbe\xfd\x34\xa6\xb8\x7f\x9f\xef\xc0\x99\xf7\x8c\x48\x56\xd1\x8c\x50\x5a\xb8\x9e\x68\x3a\xb1\xb3\xe7\x88\x9a\x66\x33\xfc\x39\xa8\x9d\x0e\xe4\xcc\xf8\xbf\x55\xc6\x77\xda\xa0\x33\xbb\x8f\xb1\xbb\xc9\x25\xc8\xd7\xa5\x7a\x11\x00\xe3\x78\x99\xb2\x0b\x07\x53\xca\x6f\x5e\x97\xea\xb5\xa3\xd8\x2b\x1e\x4a\x83\xcd\x1b\x41\xb6\x38\xf1\xbd\x27\x18\x84\x37\xc2\x24\x2a\xc9\x5c\xdc\xd1\xdb\x73\xdf\x8e\x2f\xec\x57\x4e\xfb\x5c\x10\x10\x84\x50\x59\x85\xfb\xed\x8b\xb0\xa4\xf6\x84\xcc\x53\xf7\x30\x09\x86\xe3\xf8\x7b\x00\xc7\xfd\x84\x53\xe0\xe9\xa6\x20\x06\x83\xb2\x80\x1e\x46\xdd\x84\xdd\x03\x42\xac\xce\x14\x3e\x20\x8c\xba\x29\xca\x07\x84\x98\x75\x43\xde\x0a\xd7\x13\x91\x93\xd8\x93\xc2\xfa\x05\x53\x0f\x90\x17\x28\xdc\x92\x15\x85\x87\x87\x59\x25\x41\x3e\xf3\x64\x01\xc3\xda\x73\x08\xcb\x66\x13\xff\x8a\x6f\x2f\xd6\x70\x05\x09\x67\x69\x94\x11\x1f\xe6\xd8\x47\x0a\x79\xbd\x65\xbc\x6e\x84\x2e\x21\x13\xe0\x7c\x9c\x68\xda\xf2\x34\xa9\x5e\x71\x66\xa9\x75\x91\x24\x20\x8f\x27\x59\x0a\x5b\x92\xc0\x95\xe2\x02\xaf\xe1\x1b\x22\x13\xca\x65\x25\x60\x44\x14\xdc\xa0\xdd\x96\xad\xe5\x9a\xac\xb7\xf4\x4a\xab\x80\x8c\xd8\x4f\x92\xfe\x00\x42\x0e\x1d\x02\x2f\x3b\xb5\x41\x59\xdb\xf6\x92\x48\x75\x04\x10\x95\x64\xd6\x6a\x4f\x85\xe1\xb4\xd6\xc3\x5c\xf6\xd9\x9f\x0b\x03\xc9\xb9\x0c\x38\x60\xa3\x28\x54\x22\x2e\x11\x14\x99\x5f\x94\x20\xa5\x2b\xb5\x6d\x72\xdf\x44\x2a\x1d\x56\x74\x9a\xfc\xe9\xbf\x52\xf0\x2d\x30\xcc\x92\x93\x25\x3f\x33\x22\xa4\x7a\x83\x85\x72\x68\x66\x95\x13\x91\xda\xb6\x48\xfc\x12\xac\x60\xcd\x45\xc0\x5b\x9d\x48\x3a\x93\x47\xa4\xbb\x57\xa0\x95\x12\x16\x0e\x24\x9b\x5b\x70\x78\xf8\x84\xba\x26\xb0\x51\xb9\x9a\x5e\x83\xc6\x02\x8b\x0d\x28\xe7\xf9\xc9\xe1\x6c\x23\x72\xdd\xf5\x61\xca\x1b\xc1\xb7\x24\x85\xe1\x0b\x90\xf1\xa7\xc9\xbf\x99\x33\x83\x11\xa5\xd5\xab\x28\x78\xe6\xcc\x5b\xff\xbe\xf4\xd8\x08\x45\xdc\xe9\x8c\xdf\x17\x09\xee\x20\x34\x27\xeb\x5c\xc9\x6f\xe7\x67\x60\xc2\x97\x49\x0d\xf8\x67\xbe\xa2\xfe\x31\x07\xd4\xa1\x8c\xfc\x78\xc6\x00\x9c\x2d\x6e\x96\x4c\xc7\x04\xf5\x0e\x4e\x89\xf2\x75\x1c\x3c\x12\x35\xce\xcf\x1d\x71\x2e\x96\x5f\x51\x06\x33\x11\x6e\x25\x39\x2f\x8b\xe7\xaf\xb0\x6f\x21\xba\x2f\x02\xb8\xec\x6f\x11\x0a\x07\x47\x63\xa8\x4e\xd7\x40\x2a\x87\xe2\xec\x47\x4e\x00\xb2\xc2\x8c\x81\xf8\x1a\x27\x9b\xb5\xe0\x15\x4b\x9f\x71\xea\x78\xde\x39\xfe\x7c\x50\x73\xc0\x8a\xdf\x5e\x92\xd5\x4a\x87\x5b\x47\x01\xd3\x8e\xcd\x77\x80\x53\x10\x47\x02\x92\x0a\xab\x4a\x1e\x09\x24\x27\xeb\x9c\x5a\x5d\x7a\xdc\xaa\x00\xd2\x15\x4e\x36\xd3\xc1\xf8\x78\xff\x91\xfe\xdf\x87\x47\xff\x1f\x00\x00\xff\xff\x48\x06\xf1\xfa\x52\xce\x00\x00"), - }, - } - fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ - fs["/schemas"].(os.FileInfo), - } - fs["/schemas"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ - fs["/schemas/manifest.json"].(os.FileInfo), - } - - return fs -}() - -type vfsgen۰FS map[string]interface{} - -func (fs vfsgen۰FS) Open(path string) (http.File, error) { - path = pathpkg.Clean("/" + path) - f, ok := fs[path] - if !ok { - return nil, &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist} - } - - switch f := f.(type) { - case *vfsgen۰CompressedFileInfo: - gr, err := gzip.NewReader(bytes.NewReader(f.compressedContent)) - if err != nil { - // This should never happen because we generate the gzip bytes such that they are always valid. - panic("unexpected error reading own gzip compressed bytes: " + err.Error()) - } - return &vfsgen۰CompressedFile{ - vfsgen۰CompressedFileInfo: f, - gr: gr, - }, nil - case *vfsgen۰DirInfo: - return &vfsgen۰Dir{ - vfsgen۰DirInfo: f, - }, nil - default: - // This should never happen because we generate only the above types. - panic(fmt.Sprintf("unexpected type %T", f)) - } -} - -// vfsgen۰CompressedFileInfo is a static definition of a gzip compressed file. -type vfsgen۰CompressedFileInfo struct { - name string - modTime time.Time - compressedContent []byte - uncompressedSize int64 -} - -func (f *vfsgen۰CompressedFileInfo) Readdir(count int) ([]os.FileInfo, error) { - return nil, fmt.Errorf("cannot Readdir from file %s", f.name) -} -func (f *vfsgen۰CompressedFileInfo) Stat() (os.FileInfo, error) { return f, nil } - -func (f *vfsgen۰CompressedFileInfo) GzipBytes() []byte { - return f.compressedContent -} - -func (f *vfsgen۰CompressedFileInfo) Name() string { return f.name } -func (f *vfsgen۰CompressedFileInfo) Size() int64 { return f.uncompressedSize } -func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0444 } -func (f *vfsgen۰CompressedFileInfo) ModTime() time.Time { return f.modTime } -func (f *vfsgen۰CompressedFileInfo) IsDir() bool { return false } -func (f *vfsgen۰CompressedFileInfo) Sys() interface{} { return nil } - -// vfsgen۰CompressedFile is an opened compressedFile instance. -type vfsgen۰CompressedFile struct { - *vfsgen۰CompressedFileInfo - gr *gzip.Reader - grPos int64 // Actual gr uncompressed position. - seekPos int64 // Seek uncompressed position. -} - -func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) { - if f.grPos > f.seekPos { - // Rewind to beginning. - err = f.gr.Reset(bytes.NewReader(f.compressedContent)) - if err != nil { - return 0, err - } - f.grPos = 0 - } - if f.grPos < f.seekPos { - // Fast-forward. - _, err = io.CopyN(ioutil.Discard, f.gr, f.seekPos-f.grPos) - if err != nil { - return 0, err - } - f.grPos = f.seekPos - } - n, err = f.gr.Read(p) - f.grPos += int64(n) - f.seekPos = f.grPos - return n, err -} -func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) { - switch whence { - case io.SeekStart: - f.seekPos = 0 + offset - case io.SeekCurrent: - f.seekPos += offset - case io.SeekEnd: - f.seekPos = f.uncompressedSize + offset - default: - panic(fmt.Errorf("invalid whence value: %v", whence)) - } - return f.seekPos, nil -} -func (f *vfsgen۰CompressedFile) Close() error { - return f.gr.Close() -} - -// vfsgen۰DirInfo is a static definition of a directory. -type vfsgen۰DirInfo struct { - name string - modTime time.Time - entries []os.FileInfo -} - -func (d *vfsgen۰DirInfo) Read([]byte) (int, error) { - return 0, fmt.Errorf("cannot Read from directory %s", d.name) -} -func (d *vfsgen۰DirInfo) Close() error { return nil } -func (d *vfsgen۰DirInfo) Stat() (os.FileInfo, error) { return d, nil } - -func (d *vfsgen۰DirInfo) Name() string { return d.name } -func (d *vfsgen۰DirInfo) Size() int64 { return 0 } -func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0755 | os.ModeDir } -func (d *vfsgen۰DirInfo) ModTime() time.Time { return d.modTime } -func (d *vfsgen۰DirInfo) IsDir() bool { return true } -func (d *vfsgen۰DirInfo) Sys() interface{} { return nil } - -// vfsgen۰Dir is an opened dir instance. -type vfsgen۰Dir struct { - *vfsgen۰DirInfo - pos int // Position within entries for Seek and Readdir. -} - -func (d *vfsgen۰Dir) Seek(offset int64, whence int) (int64, error) { - if offset == 0 && whence == io.SeekStart { - d.pos = 0 - return 0, nil - } - return 0, fmt.Errorf("unsupported Seek in directory %s", d.name) -} - -func (d *vfsgen۰Dir) Readdir(count int) ([]os.FileInfo, error) { - if d.pos >= len(d.entries) && count > 0 { - return nil, io.EOF - } - if count <= 0 || count > len(d.entries)-d.pos { - count = len(d.entries) - d.pos - } - e := d.entries[d.pos : d.pos+count] - d.pos += count - return e, nil -} diff --git a/assets/schemas/manifest.json b/assets/schemas/manifest.json deleted file mode 100644 index 28f8f83..0000000 --- a/assets/schemas/manifest.json +++ /dev/null @@ -1,1906 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema", - "type": "object", - "title": "Marketplace app schema", - "required": [ - "name", - "code" - ], - "dependencies": { - "requestUserAuth": ["user_auth_callback_url"] - }, - "additionalProperties": false, - "properties": { - "code": { - "type": "string", - "title": "App Code", - "default": "" - }, - "id": { - "type": "string", - "title": "App ID", - "default": "" - }, - "org": { - "type": "string", - "title": "Organization", - "default": "" - }, - "name": { - "type": "string", - "title": "App name" - }, - "version": { - "type": "string", - "title": "App semantic version", - "pattern": "^([0-9]{1,6})\\.([0-9]{1,6})\\.([0-9]{1,6})$" - }, - "autoUpgrade": { - "type": "boolean", - "title": "set to true for instances to be automatically upgraded when new versions are published" - }, - "depends": { - "type": "string", - "title": "comma-separated list of dependency requirements, $package ($version)" - }, - "provides": { - "type": "array", - "items": { - "type": "string" - }, - "title": "array of SKU's provided by this manifest" - }, - "type": { - "type": "string", - "enum": [ - "system", - "internal", - "custom" - ], - "default": "custom", - "title": "type of the package" - }, - "instances": { - "type": "string", - "enum": [ - "multiple", - "single" - ], - "default": "multiple", - "title": "number of instances allowed" - }, - "primaryCategory": { - "type": ["string", "null"], - "title": "Marketplace App primary category", - "enum": [ - "privacy", - "asset" - ] - }, - "secondaryCategory": { - "type": ["string", "null"], - "title": "Marketplace App secondary category", - "enum": [ - "privacy", - "asset" - ] - }, - "rules": { - "type": ["object", "null"], - "title": "App rules", - "additionalProperties": false, - "properties": { - "view": { - "type": "string", - "title": "rule expressing when the app is visible", - "default": "" - }, - "install": { - "type": "string", - "title": "rule expression when the app can be installed", - "default": "" - } - } - }, - "capabilities": { - "type": "array", - "title": "App capabilities", - "items": { - "type": "string", - "title": "App capability", - "enum": [ - "permitPropagation", - "permitIngestion", - "rightPropagation", - "rightIngestion", - "tagOrchestration" - ] - } - }, - "supportedLanguages": { - "type": ["array", "null"], - "title": "App supported languages", - "items": { - "type": "string", - "enum": [ - "en" - ] - } - }, - "supportedPurposes": { - "type": ["array", "null"], - "title": "App purposes", - "items": { - "type": "string", - "enum": [ - "essential_services", - "prod_enhancement", - "analytics", - "behavioral_advertising", - "personalization", - "tele_mktg", - "sms_mktg", - "email_mktg", - "mail_mktg", - "data_broking" - ] - } - }, - "supportedRights": { - "type": ["array", "null"], - "title": "App rights", - "items": { - "type": "string", - "enum": [ - "delete", - "access", - "correction", - "portability" - ] - } - }, - "shortDescription": { - "type": "string", - "title": "short description that appears in search results and galleries", - "default": "" - }, - "detailedDescription": { - "type": "string", - "title": "detailed description that appears on the app details screen", - "default": "" - }, - "permissionNote": { - "type": "string", - "title": "App permission note shown to the user when asking for authorization", - "default": "" - }, - "permissions": { - "type": ["array", "null"], - "title": "App permissions", - "items": { - "type": "string", - "title": "Permission" - } - }, - "infoURL": { - "type": "string", - "title": "App info URL" - }, - "setupURL": { - "type": "string", - "title": "App setup URL" - }, - "homepageURL": { - "type": "string", - "title": "App homepage URL" - }, - "customerSupportURL": { - "type": "string", - "title": "App customer support URL" - }, - "privacyPolicyURL": { - "type": "string", - "title": "App privacy policy URL" - }, - "statusURL": { - "type": "string", - "title": "App status URL" - }, - "tosURL": { - "type": "string", - "title": "App terms of service URL" - }, - "docURL": { - "type": "string", - "title": "App documentation URL" - }, - "logo": { - "type": ["object", "null"], - "title": "Marketplace App logo", - "required": [ - "link" - ], - "additionalProperties": false, - "dependentRequired": { - "width": ["height"], - "height": ["width"] - }, - "properties": { - "title": { - "type": "string", - "title": "logo title", - "default": "" - }, - "link": { - "type": "string", - "title": "filename" - }, - "width": { - "type": "integer", - "title": "logo width", - "default": 0 - }, - "height": { - "type": "integer", - "title": "logo height", - "default": 0 - } - } - }, - "previews": { - "type": ["array", "null"], - "title": "Marketplace App previews", - "items": { - "type": "object", - "title": "Image", - "required": [ - "link" - ], - "additionalProperties": false, - "dependentRequired": { - "width": ["height"], - "height": ["width"] - }, - "properties": { - "title": { - "type": "string", - "title": "Image title", - "default": "" - }, - "link": { - "type": "string", - "title": "Image filename" - }, - "width": { - "type": "integer", - "title": "Image width", - "default": 0 - }, - "height": { - "type": "integer", - "title": "Image height", - "default": 0 - } - } - } - }, - "contacts": { - "type": ["array", "null"], - "title": "App contacts", - "items": { - "type": "object", - "required": [ - "type", - "email" - ], - "additionalProperties": false, - "properties": { - "type": { - "type": "string", - "title": "App contact type", - "enum": [ - "technical", - "marketing", - "finance", - "security" - ] - }, - "email": { - "type": "string", - "title": "App contact email", - "format": "email" - } - } - } - }, - "expireUserTokens": { - "type": "boolean", - "title": "Expire user tokens", - "default": false - }, - "refreshInterval": { - "type": "string", - "title": "App refresh interval", - "pattern": "([1-9][0-9]*)h", - "default": "" - }, - "requestUserAuth": { - "type": "boolean", - "title": "Request user auth", - "default": false - }, - "userAuthCallbackURL": { - "type": "string", - "format": "uri", - "title": "App OAuth callback URL", - "default": "" - }, - "redirectOnUpdate": { - "type": "boolean", - "title": "Redirect on update", - "default": false - }, - "webhook": { - "type": ["object", "null"], - "title": "App webhook", - "required": [ - "url", - "events" - ], - "additionalProperties": false, - "properties": { - "url": { - "type": "string", - "format": "uri", - "title": "Webhook URI" - }, - "secret": { - "type": "string", - "title": "Base64-encoded webhook secret used to sign events", - "contentEncoding": "base64", - "default": "" - }, - "authorization": { - "type": "string", - "title": "Webhook authorization header used to authenticate to the webhook", - "default": "" - }, - "events": { - "type": ["array", "null"], - "title": "Webhook events", - "items": { - "type": "string", - "enum": [ - "ping", - "rightInvocation.created", - "rightInvocation.fulfilled", - "app.installed", - "app.refresh", - "app.uninstalled", - "consent.propagated", - "tag.activate", - "tag.deactivate", - "tag.requestList" - ] - } - }, - "maxQPS": { - "type": "integer", - "format": "int32", - "default": 100 - }, - "tls": { - "type": ["object", "null"], - "title": "TLS configuration", - "properties": { - "insecure": { - "type": "boolean" - } - } - } - } - }, - "form": { - "type": ["array", "null"], - "items": { - "type": "object", - "required": [ - "name", - "type" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The key field is where the data will be saved to. This must be unique per field.\n For example, if key = 'customers' then the value of the field will be saved in data.customers" - }, - "title": { - "type": "string", - "description": "The name or title for this component" - }, - "type": { - "type": "string", - "description": "The type property will be used to select which component to render on the frontend. It cannot be an existing field type", - "enum": [ - "array", - "string" - ] - }, - "showOnView": { - "type": "boolean", - "description": "If true, the field will appear on the connection overview", - "default": false - }, - "showValueOnEdit": { - "type": "boolean", - "description": "If false, the field value will not be shown on the edit screen", - "default": true - }, - "editable": { - "type": "boolean", - "description": "If false, the field cannot be changed", - "default": true - }, - "required": { - "type": "boolean", - "description": "If true, the field will be required to have a value" - }, - "minLength": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "maxLength": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "pattern": { - "type": "string", - "default": "" - }, - "placeholder": { - "type": "string", - "description": "The placeholder text that will appear when this field is empty", - "default": "" - }, - "default": { - "type": ["string", "null"], - "description": "Default value will be the value for this field, before user interaction. Having a default value will override the placeholder text" - }, - "spellcheck": { - "type": "boolean", - "description": "This setting will enable spell check on the field.", - "default": true - }, - "multiple": { - "type": "boolean", - "description": "If true, multiple values can be added in this field.\n The values will appear as an array in the API and an “Add Another” button will be visible on the field allowing the creation of additional fields for this component", - "default": false - }, - "data": { - "type": "object", - "properties": { - "oneOf": { - "values": { - "type": ["array", "null"], - "description": "These are the values that will be selected on this field", - "items": { - "type": "object", - "required": [ - "label", - "value" - ], - "additionalProperties": false, - "properties": { - "value": { - "type": "string" - }, - "label": { - "type": "string" - } - } - } - }, - "json": { - "type": "string", - "description": "Enter a JSON Array to use. It should be formatted as an array of objects with named properties", - "default": "" - }, - "url": { - "type": "string", - "description": "Enter a url with a data source in JSON Array format. This can be used to populate a Select list with external JSON values", - "format": "uri", - "default": "" - } - } - } - } - } - } - }, - "identitySpaces": { - "type": ["array", "null"], - "title": "App identity spaces", - "items": { - "type": "object", - "title": "App identity space", - "oneOf": [ - { - "required": [ - "code", - "name", - "filters" - ], - "properties": { - "managed": { - "type": "boolean", - "title": "Whether this identity space is managed or mapped", - "pattern": "false" - }, - "code": { - "type": "string", - "title": "App identity space code" - }, - "name": { - "type": "string", - "title": "App identity space name" - }, - "description": { - "type": "string", - "title": "App identity space description", - "default": "" - }, - "filters": { - "type": "array", - "title": "App identity space filters", - "items": { - "type": "object", - "title": "A filter", - "required": [ - "type", - "format" - ], - "additionalProperties": false, - "properties": { - "type": { - "type": "string", - "title": "App identity space filter type", - "enum": [ - "email", - "controller_customer_id", - "android_advertising_id", - "android_id", - "fire_advertising_id", - "ios_advertising_id", - "ios_vendor_id", - "microsoft_advertising_id", - "microsoft_publisher_id", - "roku_publisher_id", - "roku_advertising_id", - "unique_browser", - "telephone" - ] - }, - "format": { - "type": "string", - "title": "App identity space filter format", - "enum": [ - "raw", - "SHA1", - "SHA256", - "SHA512" - ] - } - } - } - } - } - }, - { - "required": [ - "code", - "name", - "type", - "variable" - ], - "properties": { - "managed": { - "type": "boolean", - "title": "Whether this identity space is managed or mapped", - "pattern": "true" - }, - "code": { - "type": "string", - "title": "App identity space code" - }, - "name": { - "type": "string", - "title": "App identity space name" - }, - "description": { - "type": "string", - "title": "App identity space description", - "default": "" - }, - "type": { - "type": "string", - "title": "App identity space filter type", - "enum": [ - "email", - "controller_customer_id", - "android_advertising_id", - "android_id", - "fire_advertising_id", - "ios_advertising_id", - "ios_vendor_id", - "microsoft_advertising_id", - "microsoft_publisher_id", - "roku_publisher_id", - "roku_advertising_id", - "unique_browser", - "telephone" - ] - }, - "format": { - "type": "string", - "title": "App identity space filter format", - "default": "raw", - "enum": [ - "raw", - "sha1", - "sha256", - "sha512" - ] - }, - "variable": { - "type": "object", - "title": "Variable definition", - "required": [ - "location", - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "title": "Name of the variable" - }, - "location": { - "type": "string", - "title": "Location of the variable", - "enum": [ - "window", - "cookie", - "dataLayer" - ] - }, - "jwt": { - "type": ["object", "null"], - "title": "JWT details", - "required": [ - "location", - "key" - ], - "additionalProperties": false, - "properties": { - "location": { - "type": "string", - "title": "location to find the variable within the JWT", - "enum": [ - "header", - "claims" - ] - }, - "key": { - "type": "string", - "title": "key of the variable within the JWT" - } - } - } - } - } - } - } - ] - } - }, - "workflows": { - "type": ["array", "null"], - "title": "definition of workflows", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string", - "title": "code of the workflow" - }, - "name": { - "type": "string", - "title": "name of the workflow" - }, - "readonly": { - "type": "boolean", - "title": "set true to make the workflow not editable", - "default": "false" - }, - "options": { - "type": "object", - "title": "options for starting the workflow", - "properties": { - "taskQueue": { - "type": "string" - }, - "workflowExecutionTimeout": { - "type": "integer", - "format": "int64" - }, - "workflowRunTimeout": { - "type": "integer", - "format": "int64" - }, - "workflowTaskTimeout": { - "type": "integer", - "format": "int64" - }, - "memo": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "searchAttributes": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "retryPolicy": { - "type": "object", - "properties": { - "initialInterval": { - "type": "integer", - "format": "int64" - }, - "backoffCoefficient": { - "type": "integer", - "format": "double" - }, - "maximumInterval": { - "type": "integer", - "format": "int64" - }, - "maximumAttempts": { - "type": "integer", - "format": "int64" - }, - "nonRetryableErrorReasons": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "steps": { - "type": "array", - "items": { - "type": "object", - "title": "step represents a step in a workflow.", - "properties": { - "activity": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "code": { - "type": "string" - }, - "description": { - "type": "string" - }, - "step": { - "type": "string" - }, - "fn": { - "type": "string" - }, - "next": { - "type": "string" - }, - "options": { - "type": "object", - "properties": { - "taskQueue": { - "type": "string" - }, - "scheduleToCloseTimeout": { - "type": "integer", - "format": "int64" - }, - "scheduleToStartTimeout": { - "type": "integer", - "format": "int64" - }, - "startToCloseTimeout": { - "type": "integer", - "format": "int64" - }, - "heartbeatTimeout": { - "type": "integer", - "format": "int64" - }, - "waitForCancellation": { - "type": "boolean" - }, - "retryPolicy": { - "type": "string", - "enum": [ - "terminate", - "requestCancel", - "abandon" - ] - } - } - }, - "params": { - "type": "object", - "additionalProperties": true - } - } - }, - "childWorkflow": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "code": { - "type": "string" - }, - "description": { - "type": "string" - }, - "step": { - "type": "string" - }, - "fn": { - "type": "string" - }, - "next": { - "type": "string" - }, - "options": { - "type": "object", - "properties": { - "taskQueue": { - "type": "string" - }, - "workflowExecutionTimeout": { - "type": "integer", - "format": "int64" - }, - "workflowRunTimeout": { - "type": "integer", - "format": "int64" - }, - "workflowTaskTimeout": { - "type": "integer", - "format": "int64" - }, - "waitForCancellation": { - "type": "boolean" - }, - "parentClosePolicy": { - "type": "string", - "enum": [ - "terminate", - "requestCancel", - "abandon" - ] - }, - "memo": { - "type": "object", - "additionalProperties": true - }, - "searchAttributes": { - "type": "object", - "additionalProperties": true - }, - "retryPolicy": { - "type": "object", - "properties": { - "initialInterval": { - "type": "integer", - "format": "int64" - }, - "backoffCoefficient": { - "type": "number", - "format": "double" - }, - "maximumInterval": { - "type": "integer", - "format": "int64" - }, - "maximumAttempts": { - "type": "integer", - "format": "int64" - }, - "nonRetryableErrorReasons": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "params": { - "type": "object", - "additionalProperties": true - } - } - }, - "gateway": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "code": { - "type": "string" - }, - "description": { - "type": "string" - }, - "mode": { - "type": "string", - "enum": [ - "split", - "join", - "single", - "multi" - ] - }, - "next": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "variable": { - "type": "string" - }, - "operator": { - "type": "string" - }, - "operand": { - "type": "string" - } - } - } - } - } - }, - "start": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "code": { - "type": "string" - }, - "description": { - "type": "string" - }, - "next": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - } - } - }, - "finish": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "code": { - "type": "string" - }, - "description": { - "type": "string" - }, - "params": { - "type": "object", - "additionalProperties": true - } - } - } - } - } - } - } - } - }, - "activities": { - "type": ["array", "null"], - "title": "definition of activity objects", - "items": { - "type": "object", - "required": [ - "code", - "name", - "icon", - "fn" - ], - "additionalProperties": false, - "properties": { - "code": { - "type": "string", - "title": "human-readable identifier for the object" - }, - "name": { - "type": "string", - "title": "name of the Activity as shown to the user" - }, - "icon": { - "type": "string", - "title": "filename of the icon to show" - }, - "fn": { - "type": "string", - "title": "the function to be executed" - }, - "options": { - "type": ["object", "null"], - "title": "the options for the workflow object", - "additionalProperties": false, - "properties": { - "task_queue": { - "type": "string", - "default": "" - }, - "workflow_execution_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "workflow_run_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "workflow_task_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "wait_for_cancellation": { - "type": "boolean", - "default": false - }, - "schedule_to_close_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "schedule_to_start_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "start_to_close_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "heartbeat_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - } - } - }, - "params": { - "type": ["array", "null"], - "title": "parameters", - "items": { - "type": "object", - "required": [ - "code", - "name", - "type" - ], - "additionalProperties": false, - "properties": { - "code": { - "type": "string", - "title": "human-readable unique identifier of the parameter" - }, - "name": { - "type": "string", - "title": "user-friendly name of the parameter" - }, - "type": { - "type": "string", - "title": "type of the parameter" - }, - "default": { - "type": "string", - "title": "default value of the parameter" - } - } - } - }, - "outputs": { - "type": ["array", "null"], - "title": "output values", - "items": { - "type": "object", - "required": [ - "code", - "name", - "type" - ], - "additionalProperties": false, - "properties": { - "code": { - "type": "string", - "title": "human-readable unique identifier of the output" - }, - "name": { - "type": "string", - "title": "user-friendly name of the output" - }, - "type": { - "type": "string", - "title": "type of the output" - }, - "default": { - "type": "string", - "title": "default value of the output" - } - } - } - }, - "config": { - "type": "object", - "additionalProperties": true - } - } - } - }, - "childWorkflows": { - "type": ["array", "null"], - "title": "definition of child workflow objects", - "items": { - "type": "object", - "required": [ - "code", - "name", - "icon", - "fn" - ], - "additionalProperties": false, - "properties": { - "code": { - "type": "string", - "title": "human-readable identifier for the object" - }, - "name": { - "type": "string", - "title": "name of the Activity as shown to the user" - }, - "icon": { - "type": "string", - "title": "filename of the icon to show" - }, - "fn": { - "type": "string", - "title": "the function to be executed" - }, - "options": { - "type": ["object", "null"], - "title": "the options for the workflow object", - "additionalProperties": false, - "properties": { - "task_queue": { - "type": "string", - "default": "" - }, - "workflow_execution_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "workflow_run_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "workflow_task_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "wait_for_cancellation": { - "type": "boolean", - "default": false - }, - "schedule_to_close_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "schedule_to_start_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "start_to_close_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "heartbeat_timeout": { - "type": "integer", - "format": "int64", - "default": 0 - } - } - }, - "params": { - "type": ["array", "null"], - "title": "parameters", - "items": { - "type": "object", - "required": [ - "code", - "name", - "type" - ], - "additionalProperties": false, - "properties": { - "code": { - "type": "string", - "title": "human-readable unique identifier of the parameter" - }, - "name": { - "type": "string", - "title": "user-friendly name of the parameter" - }, - "type": { - "type": "string", - "title": "type of the parameter" - }, - "default": { - "type": "string", - "title": "default value of the parameter" - } - } - } - }, - "outputs": { - "type": ["array", "null"], - "title": "output values", - "items": { - "type": "object", - "required": [ - "code", - "name", - "type" - ], - "additionalProperties": false, - "properties": { - "code": { - "type": "string", - "title": "human-readable unique identifier of the output" - }, - "name": { - "type": "string", - "title": "user-friendly name of the output" - }, - "type": { - "type": "string", - "title": "type of the output" - }, - "default": { - "type": "string", - "title": "default value of the output" - } - } - } - }, - "config": { - "type": "object", - "additionalProperties": true - } - } - } - }, - "purposes": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "tcfId": { - "type": "integer" - }, - "tcfType": { - "type": "string", - "enum": [ - "purpose", - "specialPurpose", - "feature", - "specialFeature" - ] - }, - "editable": { - "type": "boolean", - "default": false - }, - "required": { - "type": "boolean", - "default": false - }, - "legalBasisRestriction": { - "type": "array", - "items": { - "type": "string" - } - }, - "displayName": { - "type": "string" - }, - "displayDescription": { - "type": "string" - }, - "processingPurpose": { - "type": "string" - }, - "legalBasis": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "cookies": { - "type": "array", - "items": { - "type": "string" - } - }, - "canonicalPurposes": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "essential_services", - "prod_enhancement", - "analytics", - "behavioral_advertising", - "personalization", - "tele_mktg", - "sms_mktg", - "email_mktg", - "mail_mktg", - "data_broking" - ] - } - }, - "translations": { - "type": "object", - "items": { - "type": "object", - "additionalProperties": true - } - }, - "dataSubjectRole": { - "type": "string", - "enum": [ - "customer", - "employee" - ] - }, - "dataRole": { - "type": "string", - "enum": [ - "processor", - "controller", - "jointController", - "jointProcessor", - "coController" - ] - } - } - } - }, - "purposeTemplates": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "tcfId": { - "type": "integer" - }, - "tcfType": { - "type": "string", - "enum": [ - "purpose", - "specialPurpose", - "feature", - "specialFeature" - ] - }, - "editable": { - "type": "boolean", - "default": false - }, - "required": { - "type": "boolean", - "default": false - }, - "legalBasisRestrictions": { - "type": "array", - "items": { - "type": "string" - } - }, - "displayName": { - "type": "string" - }, - "displayDescription": { - "type": "string" - }, - "legalBasis": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "cookies": { - "type": "array", - "items": { - "type": "string" - } - }, - "canonicalPurposes": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "essential_services", - "prod_enhancement", - "analytics", - "behavioral_advertising", - "personalization", - "tele_mktg", - "sms_mktg", - "email_mktg", - "mail_mktg", - "data_broking" - ] - } - }, - "translations": { - "type": "object", - "items": { - "type": "object", - "additionalProperties": true - } - }, - "dataSubjectRole": { - "type": "string", - "enum": [ - "customer", - "employee" - ] - }, - "dataRole": { - "type": "string", - "enum": [ - "processor", - "controller", - "jointController", - "jointProcessor", - "coController" - ] - }, - "collections": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "legalBasisRestrictions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "regulation": { - "type": "string" - }, - "legalBases": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "policyScopes": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "regions": { - "type": "array", - "items": { - "type": "string" - } - }, - "regulations": { - "type": "array", - "items": { - "type": "string" - } - }, - "fulfillment": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - } - } - } - }, - "policyScopeTemplates": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "regions": { - "type": "array", - "items": { - "type": "string" - } - }, - "regulations": { - "type": "array", - "items": { - "type": "string" - } - }, - "fulfillment": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - } - } - } - }, - "legalBases": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "requiresOptIn": { - "type": "boolean" - }, - "allowOptOut": { - "type": "boolean" - }, - "requiresPrivacyPolicy": { - "type": "boolean" - } - } - } - }, - "tcf": { - "type": "object", - "properties": { - "vendor": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "purposes": { - "type": "array", - "items": { - "type": "string" - } - }, - "specialPurposes": { - "type": "array", - "items": { - "type": "string" - } - }, - "features": { - "type": "array", - "items": { - "type": "string" - } - }, - "specialFeatures": { - "type": "array", - "items": { - "type": "string" - } - }, - "policyUrl": { - "type": "string" - }, - "legIntPurposes": { - "type": "array", - "items": { - "type": "string" - } - }, - "flexiblePurposes": { - "type": "array", - "items": { - "type": "string" - } - }, - "usesCookies": { - "type": "boolean" - }, - "cookieMaxAgeSeconds": { - "type": "integer", - "format": "int64", - "default": 0 - }, - "cookieRefresh": { - "type": "boolean" - }, - "usesNonCookieAccess": { - "type": "boolean" - }, - "deviceStorageDisclosureUrl": { - "type": "boolean" - } - } - }, - "gvlSpecificationVersion": { - "type": "string" - }, - "vendorListVersion": { - "type": "string" - }, - "tcfPolicyVersion": { - "type": "string" - } - } - }, - "cookies": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "host": { - "type": "string" - }, - "duration": { - "type": "string", - "enum": [ - "session", - "persistent" - ] - }, - "provenance": { - "type": "string", - "enum": [ - "firstParty", - "thirdParty" - ] - }, - "category": { - "type": "string", - "enum": [ - "strictlyNecessary", - "functional", - "performance", - "marketing", - "analytics" - ] - }, - "serviceProvider": { - "type": "string" - }, - "translations": { - "type": "object", - "items": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "purposeTemplateCollections": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - } - } - } - }, - "regulations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "rightsFulfillment": { - "type": "object", - "properties": { - "rightCode": { - "type": "string" - }, - "fulfillment": { - "type": "string" - } - } - } - } - } - }, - "rights": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "translations": { - "type": "object", - "items": { - "type": "object", - "additionalProperties": true - } - }, - "canonicalRights": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "themes": { - "type": "array", - "items": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "bannerBackgroundColor": { - "type": "string" - }, - "lightboxRibbonColor": { - "type": "string" - }, - "formHeaderColor": { - "type": "string" - }, - "statusColor": { - "type": "string" - }, - "highlightColor": { - "type": "string" - }, - "feedbackColor": { - "type": "string" - } - } - } - } - } -} diff --git a/auth/login.go b/auth/login.go deleted file mode 100644 index 8cc95c3..0000000 --- a/auth/login.go +++ /dev/null @@ -1,150 +0,0 @@ -package auth - -import ( - "bytes" - "encoding/json" - "fmt" - "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/config" - "go.ketch.com/lib/orlop" - "go.ketch.com/lib/orlop/errors" - "net/http" - "net/url" - "time" -) - -const ClientID = "TODO" - -type GetDeviceCodeRequest struct { - // The client identifier - ClientID string `json:"client_id,omitempty"` - - // The scope of the access request - Scope string `json:"scope,omitempty"` -} - -type DeviceCode struct { - // The device verification code. - DeviceCode string `json:"device_code,omitempty"` - - // The end-user verification code. - UserCode string `json:"user_code"` - - // The end-user verification URI on the authorization - // server. The URI should be short and easy to remember as end users - // will be asked to manually type it into their user agent. - VerificationUri string `json:"verification_uri"` - - // A verification URI that includes the "user_code" (or - // other information with the same function as the "user_code"), - // which is designed for non-textual transmission. - VerificationUriComplete string `json:"verification_uri_complete"` - - // The lifetime in seconds of the "device_code" and "user_code". - ExpiresInSec int64 `json:"expires_in"` - - // The minimum amount of time in seconds that the client - // SHOULD wait between polling requests to the token endpoint. If no - // value is provided, clients MUST use 5 as the default. - IntervalInSec int64 `json:"interval"` -} - -type Token struct { - AccessToken string `json:"access_token,omitempty"` - TokenType string `json:"token_type,omitempty"` - ExpiresInSec int64 `json:"expires_in,omitempty"` - RefreshToken string `json:"refresh_token,omitempty"` -} - -func Login(cmd *cobra.Command, args []string) error { - var err error - - ctx := cmd.Context() - cfg := config.GetFromContext(ctx) - - codeRequest := make(url.Values) - codeRequest.Set("client_id", ClientID) - - buf := bytes.NewReader([]byte(codeRequest.Encode())) - - tp := http.DefaultTransport.(*http.Transport).Clone() - if tp.TLSClientConfig, err = orlop.NewClientTLSConfigContext(ctx, cfg.TLS, cfg.Vault); err != nil { - return err - } - - cli := http.Client{ - Transport: tp, - } - - req, err := http.NewRequestWithContext(ctx, http.MethodPost, cfg.URL+"/device/code", buf) - if err != nil { - return err - } - - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - resp, err := cli.Do(req) - if err != nil { - return err - } - - if resp.StatusCode == 200 { - defer resp.Body.Close() - - var dc DeviceCode - - err := json.NewDecoder(resp.Body).Decode(&dc) - if err != nil { - return err - } - - fmt.Printf("Now, go to %s and enter the following code:\n", dc.VerificationUri) - fmt.Printf("%s\n", dc.UserCode) - - timeout := time.After(time.Duration(dc.ExpiresInSec) * time.Second) - ticker := time.NewTicker(time.Duration(dc.IntervalInSec) * time.Second) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return nil - - case <-ticker.C: - tokenRequest := make(url.Values) - tokenRequest.Set("grant_type", "urn:ietf:params:oauth:grant-type:device_code") - tokenRequest.Set("client_id", ClientID) - tokenRequest.Set("device_code", dc.DeviceCode) - - buf := bytes.NewReader([]byte(codeRequest.Encode())) - - tp := http.DefaultTransport.(*http.Transport).Clone() - if tp.TLSClientConfig, err = orlop.NewClientTLSConfigContext(ctx, cfg.TLS, cfg.Vault); err != nil { - return err - } - - cli := http.Client{ - Transport: tp, - } - - req, err := http.NewRequestWithContext(ctx, http.MethodPost, cfg.URL+"/token", buf) - if err != nil { - return err - } - - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - resp, err := cli.Do(req) - if err != nil { - return err - } - - fmt.Println(resp.Body) - continue - - case <-timeout: - return errors.New("login: timed out") - } - } - } else { - return errors.Errorf("login: status %s", resp.Status) - } -} diff --git a/cli/app_publish.go b/cli/app_publish.go new file mode 100644 index 0000000..1d17bf9 --- /dev/null +++ b/cli/app_publish.go @@ -0,0 +1,73 @@ +package cli + +import ( + "github.com/spf13/cobra" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/cli/ketch-cli/flags" + "go.ketch.com/cli/ketch-cli/services/impl" + "net/http" +) + +func PublishApp(cmd *cobra.Command, args []string) error { + var err error + ctx := cmd.Context() + + validatorConfig := &config.ValidatorConfig{} + + loaderConfig := &config.LoaderConfig{} + + if loaderConfig.AppConfigFile, err = cmd.Flags().GetString(flags.File); err != nil { + return err + } + + if loaderConfig.Version, err = cmd.Flags().GetString(flags.Version); err != nil { + return err + } + + if loaderConfig.PluginFilename, err = cmd.Flags().GetString(flags.Plugin); err != nil { + return err + } + + if loaderConfig.ObjectsDir, err = cmd.Flags().GetString(flags.Objects); err != nil { + return err + } + + if loaderConfig.AssetsDir, err = cmd.Flags().GetString(flags.Assets); err != nil { + return err + } + + if loaderConfig.Env, err = cmd.Flags().GetStringToString(flags.Env); err != nil { + return err + } + + publisherConfig := &config.PublisherConfig{} + + if publisherConfig.AccessToken, err = cmd.Flags().GetString(flags.Token); err != nil { + return err + } + + if publisherConfig.URL, err = cmd.Flags().GetString(flags.URL); err != nil { + return err + } + + validator := impl.NewValidator(validatorConfig, impl.NewReporter()) + loader := impl.NewLoader(impl.NewReporter(), &http.Client{}) + publisher := impl.NewPublisher(publisherConfig) + + manifest, err := loader.Load(ctx, loaderConfig) + if err != nil { + return err + } + + err = validator.Validate(ctx, manifest) + if err != nil { + return err + } + + err = publisher.Publish(ctx, manifest) + if err != nil { + return err + } + + return nil +} diff --git a/cli/app_validate.go b/cli/app_validate.go new file mode 100644 index 0000000..6614062 --- /dev/null +++ b/cli/app_validate.go @@ -0,0 +1,44 @@ +package cli + +import ( + "github.com/spf13/cobra" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/cli/ketch-cli/flags" + "go.ketch.com/cli/ketch-cli/services/impl" + "net/http" +) + +func ValidateApp(cmd *cobra.Command, args []string) error { + var err error + + ctx := cmd.Context() + + validatorConfig := &config.ValidatorConfig{} + + loaderConfig := &config.LoaderConfig{ + Version: "0.0.0", + } + + if loaderConfig.AppConfigFile, err = cmd.Flags().GetString(flags.File); err != nil { + return err + } + + if loaderConfig.Env, err = cmd.Flags().GetStringToString(flags.Env); err != nil { + return err + } + + reporter := impl.NewReporter() + + loader := impl.NewLoader(reporter, &http.Client{}) + + manifest, err := loader.Load(ctx, loaderConfig) + if err != nil { + return err + } + + if err = impl.NewValidator(validatorConfig, reporter).Validate(ctx, manifest); err != nil { + return err + } + + return nil +} diff --git a/config/tls.go b/cli/tls.go similarity index 90% rename from config/tls.go rename to cli/tls.go index 88b76ba..58f671b 100644 --- a/config/tls.go +++ b/cli/tls.go @@ -1,4 +1,4 @@ -package config +package cli import ( "github.com/spf13/cobra" @@ -6,7 +6,7 @@ import ( "go.ketch.com/lib/orlop" ) -func GetTLSConfig(cmd *cobra.Command) (*orlop.TLSConfig, error) { +func getTLSConfig(cmd *cobra.Command) (*orlop.TLSConfig, error) { var err error tls := &orlop.TLSConfig{} if tls.Insecure, err = cmd.Flags().GetBool(flags.TLSInsecure); err != nil { diff --git a/webhooks/send.go b/cli/webhook_send.go similarity index 96% rename from webhooks/send.go rename to cli/webhook_send.go index 5938733..bddadfd 100644 --- a/webhooks/send.go +++ b/cli/webhook_send.go @@ -1,10 +1,9 @@ -package webhooks +package cli import ( "encoding/json" cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/config" "go.ketch.com/cli/ketch-cli/flags" "go.ketch.com/lib/oid" "go.ketch.com/lib/orlop" @@ -79,7 +78,7 @@ func SendWebhookEvent(cmd *cobra.Command, args []string) error { Secret: secretToken, } - tls, err := config.GetTLSConfig(cmd) + tls, err := getTLSConfig(cmd) if err != nil { return err } diff --git a/webhooks/validate.go b/cli/webhook_validate.go similarity index 84% rename from webhooks/validate.go rename to cli/webhook_validate.go index bd08cd5..6945ce3 100644 --- a/webhooks/validate.go +++ b/cli/webhook_validate.go @@ -1,14 +1,13 @@ -package webhooks +package cli import ( "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/config" "go.ketch.com/cli/ketch-cli/flags" "go.ketch.com/lib/orlop" "go.ketch.com/lib/webhook-client/webhook" ) -func Validate(cmd *cobra.Command, args []string) error { +func ValidateWebhook(cmd *cobra.Command, args []string) error { var err error vault := &orlop.VaultConfig{} @@ -36,7 +35,7 @@ func Validate(cmd *cobra.Command, args []string) error { Secret: secretToken, } - tls, err := config.GetTLSConfig(cmd) + tls, err := getTLSConfig(cmd) if err != nil { return err } diff --git a/cmd/ketch/commands/login.go b/cmd/ketch/commands/login.go deleted file mode 100644 index ea60229..0000000 --- a/cmd/ketch/commands/login.go +++ /dev/null @@ -1,17 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/auth" -) - -func init() { - var login = &cobra.Command{ - RunE: auth.Login, - Use: "login", - Short: "Connect the CLI to your Ketch account by logging in to persist your secret key locally.", - Args: cobra.NoArgs, - } - - rootCmd.AddCommand(login) -} diff --git a/cmd/ketch/commands/publish.go b/cmd/ketch/commands/publish.go deleted file mode 100644 index fc23a05..0000000 --- a/cmd/ketch/commands/publish.go +++ /dev/null @@ -1,28 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/apps" - "go.ketch.com/cli/ketch-cli/flags" - "os" -) - -func init() { - var publish = &cobra.Command{ - RunE: apps.Publish, - Use: "publish", - Short: "publish an app", - } - - publish.Flags().StringP(flags.File, "f", "ketch-manifest.yml", "app config name") - publish.Flags().String(flags.Version, os.Getenv("KETCH_VERSION"), "app version") - publish.Flags().String(flags.Token, os.Getenv("KETCH_TOKEN"), "token for Ketch API") - publish.Flags().String(flags.URL, os.Getenv("KETCH_URL"), "url to Ketch API") - publish.Flags().Bool(flags.TLSInsecure, false, "set true to skip certificate verification") - publish.Flags().String(flags.TLSCert, "", "TLS client certificate") - publish.Flags().String(flags.TLSKey, "", "TLS private key") - publish.Flags().String(flags.TLSCACert, "", "TLS root CA certificate") - publish.Flags().String(flags.TLSServerName, "", "override the TLS server name") - - rootCmd.AddCommand(publish) -} diff --git a/cmd/ketch/commands/root.go b/cmd/ketch/commands/root.go deleted file mode 100644 index 798cee2..0000000 --- a/cmd/ketch/commands/root.go +++ /dev/null @@ -1,48 +0,0 @@ -package commands - -import ( - "context" - "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/config" - "go.ketch.com/cli/ketch-cli/flags" - "go.ketch.com/cli/ketch-cli/version" - "os" -) - -var rootCmd = &cobra.Command{ - Use: version.Name, - Short: version.Description, - Version: version.String(), - TraverseChildren: true, -} - -// Execute executes the command. -func Execute(ctx context.Context, cfg *config.Config) error { - rootCmd.SetHelpCommand(&cobra.Command{ - Use: "help [command]", - Short: "help about any command", - Long: `Help provides help for any command in the application. -Simply type ` + rootCmd.Name() + ` help [path to command] for full details.`, - - Run: func(c *cobra.Command, args []string) { - cmd, _, e := c.Root().Find(args) - if cmd == nil || e != nil { - c.Printf("Unknown help topic %#q\n", args) - c.Root().Usage() - } else { - cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown - cmd.Help() - } - }, - }) - - rootCmd.PersistentFlags().String(flags.Token, os.Getenv("KETCH_TOKEN"), "auth token") - rootCmd.SilenceUsage = true - - ctx = config.AddToContext(ctx, cfg) - if err := rootCmd.ExecuteContext(ctx); err != nil { - return err - } - - return nil -} diff --git a/cmd/ketch/commands/validate.go b/cmd/ketch/commands/validate.go deleted file mode 100644 index 2cef857..0000000 --- a/cmd/ketch/commands/validate.go +++ /dev/null @@ -1,19 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/apps" - "go.ketch.com/cli/ketch-cli/flags" -) - -func init() { - var validate = &cobra.Command{ - RunE: apps.Validate, - Use: "validate", - Short: "validate an app manifest file", - } - - validate.Flags().StringP(flags.File, "f", "ketch-manifest.yml", "app config name") - - rootCmd.AddCommand(validate) -} diff --git a/cmd/ketch/commands/webhook.go b/cmd/ketch/commands/webhook.go deleted file mode 100644 index 54bce01..0000000 --- a/cmd/ketch/commands/webhook.go +++ /dev/null @@ -1,49 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" - "go.ketch.com/cli/ketch-cli/flags" - "go.ketch.com/cli/ketch-cli/webhooks" -) - -func init() { - var webhookCmd = &cobra.Command{ - Use: "webhook", - Short: "commands related to WebHooks", - } - - webhookCmd.PersistentFlags().Uint64(flags.QPS, 10, "maximum QPS") - webhookCmd.PersistentFlags().String(flags.Auth, "", "authorization header") - webhookCmd.PersistentFlags().BytesBase64(flags.Secret, nil, "shared secret") - webhookCmd.PersistentFlags().Bool(flags.TLSInsecure, false, "set true to skip certificate verification") - webhookCmd.PersistentFlags().String(flags.TLSCert, "", "TLS client certificate") - webhookCmd.PersistentFlags().String(flags.TLSKey, "", "TLS private key") - webhookCmd.PersistentFlags().String(flags.TLSCACert, "", "TLS root CA certificate") - webhookCmd.PersistentFlags().String(flags.TLSServerName, "", "override the TLS server name") - - var webhookSendCmd = &cobra.Command{ - RunE: webhooks.SendWebhookEvent, - Use: "send", - Short: "send event to the webhook specified", - Args: cobra.ExactArgs(1), - } - - webhookSendCmd.Flags().String(flags.EventType, "", "event type") - webhookSendCmd.Flags().String(flags.EventSource, "", "event source") - webhookSendCmd.Flags().StringP(flags.File, "f", "", "filename") - webhookSendCmd.Flags().String(flags.Org, "", "organization code") - webhookSendCmd.Flags().String(flags.AppID, "", "appID") - - webhookCmd.AddCommand(webhookSendCmd) - - var webhookValidateCmd = &cobra.Command{ - RunE: webhooks.Validate, - Use: "validate", - Short: "validate the given webhook", - Args: cobra.ExactArgs(1), - } - - webhookCmd.AddCommand(webhookValidateCmd) - - rootCmd.AddCommand(webhookCmd) -} diff --git a/cmd/ketch/main.go b/cmd/ketch/main.go index 6359948..ac08c65 100644 --- a/cmd/ketch/main.go +++ b/cmd/ketch/main.go @@ -4,16 +4,126 @@ import ( "context" "github.com/joho/godotenv" "github.com/sirupsen/logrus" - "go.ketch.com/cli/ketch-cli/cmd/ketch/commands" - "go.ketch.com/cli/ketch-cli/config" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "go.ketch.com/cli/ketch-cli/cli" + "go.ketch.com/cli/ketch-cli/flags" "go.ketch.com/cli/ketch-cli/version" - "go.ketch.com/lib/orlop" "go.ketch.com/lib/orlop/log" stdlog "log" "os" "path" ) +func tlsFlags(f *pflag.FlagSet) { + f.Bool(flags.TLSInsecure, os.Getenv("KETCH_TLS_INSECURE") == "true", "set true to skip certificate verification") + f.String(flags.TLSCert, os.Getenv("KETCH_TLS_CERT_FILE"), "TLS client certificate") + f.String(flags.TLSKey, os.Getenv("KETCH_TLS_KEY_FILE"), "TLS private key") + f.String(flags.TLSCACert, os.Getenv("KETCH_TLS_CACERT_FILE"), "TLS root CA certificate") + f.String(flags.TLSServerName, os.Getenv("KETCH_TLS_SERVER_NAME"), "override the TLS server name") +} + +// Execute executes the command. +func Execute(ctx context.Context) error { + var rootCmd = &cobra.Command{ + Use: version.Name, + Short: version.Description, + Version: version.String(), + TraverseChildren: true, + SilenceUsage: true, + } + + rootCmd.SetHelpCommand(&cobra.Command{ + Use: "help [command]", + Short: "help about any command", + Long: `Help provides help for any command in the application. +Simply type ` + rootCmd.Name() + ` help [path to command] for full details.`, + + Run: func(c *cobra.Command, args []string) { + cmd, _, e := c.Root().Find(args) + if cmd == nil || e != nil { + c.Printf("Unknown help topic %#q\n", args) + c.Root().Usage() + } else { + cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown + cmd.Help() + } + }, + }) + + var publish = &cobra.Command{ + RunE: cli.PublishApp, + Use: "publish", + Short: "publish an App", + } + + publish.Flags().StringP(flags.File, "f", "ketch-manifest.yml", "app object file") + publish.Flags().String(flags.Version, os.Getenv("KETCH_VERSION"), "app version") + publish.Flags().String(flags.Plugin, os.Getenv("KETCH_PLUGIN"), "path to the plugin.js file") + publish.Flags().String(flags.Objects, os.Getenv("KETCH_OBJECTS"), "path to the objects directory") + publish.Flags().String(flags.Assets, os.Getenv("KETCH_ASSETS"), "path to the assets directory") + publish.Flags().StringToStringP(flags.Env, "E", nil, "environment variables") + publish.Flags().String(flags.Token, os.Getenv("KETCH_TOKEN"), "token for Ketch API") + publish.Flags().String(flags.URL, os.Getenv("KETCH_URL"), "url to Ketch API") + + tlsFlags(publish.Flags()) + + rootCmd.AddCommand(publish) + + var validate = &cobra.Command{ + RunE: cli.ValidateApp, + Use: "validate", + Short: "validate an App", + } + + validate.Flags().StringP(flags.File, "f", "ketch-manifest.yml", "app object file") + validate.Flags().StringToStringP(flags.Env, "E", nil, "environment variables") + + rootCmd.AddCommand(validate) + + var webhookCmd = &cobra.Command{ + Use: "webhook", + Short: "commands related to WebHooks", + } + + webhookCmd.PersistentFlags().Uint64(flags.QPS, 10, "maximum QPS") + webhookCmd.PersistentFlags().String(flags.Auth, "", "authorization header") + webhookCmd.PersistentFlags().BytesBase64(flags.Secret, nil, "shared secret") + tlsFlags(webhookCmd.PersistentFlags()) + + var webhookSendCmd = &cobra.Command{ + RunE: cli.SendWebhookEvent, + Use: "send", + Short: "send event to the webhook specified", + Args: cobra.ExactArgs(1), + } + + webhookSendCmd.Flags().String(flags.EventType, "", "event type") + webhookSendCmd.Flags().String(flags.EventSource, "", "event source") + webhookSendCmd.Flags().StringP(flags.File, "f", "", "filename") + webhookSendCmd.Flags().String(flags.Org, "", "organization code") + webhookSendCmd.Flags().String(flags.AppID, "", "appID") + + webhookCmd.AddCommand(webhookSendCmd) + + var webhookValidateCmd = &cobra.Command{ + RunE: cli.ValidateWebhook, + Use: "validate", + Short: "validate the given webhook", + Args: cobra.ExactArgs(1), + } + + webhookCmd.AddCommand(webhookValidateCmd) + + rootCmd.AddCommand(webhookCmd) + + if err := rootCmd.ExecuteContext(ctx); err != nil { + return err + } + + return nil +} + func main() { homeDir, err := os.UserHomeDir() if err != nil { @@ -28,12 +138,6 @@ func main() { } } - cfg := &config.Config{} - if err = orlop.Unmarshal(version.Name, cfg); err != nil { - log.Fatal(err) - return - } - logrus.SetFormatter(&logrus.TextFormatter{ ForceColors: true, DisableTimestamp: true, @@ -43,7 +147,7 @@ func main() { stdlog.SetOutput(logrus.New().Writer()) - if err = commands.Execute(context.Background(), cfg); err != nil { + if err = Execute(context.Background()); err != nil { os.Exit(1) } } diff --git a/config/config.go b/config/config.go index 5436080..ae49868 100644 --- a/config/config.go +++ b/config/config.go @@ -1,29 +1,18 @@ package config -import ( - "context" - "go.ketch.com/lib/orlop" -) - -type Config struct { - URL string - Host string - Port int32 - TLS orlop.TLSConfig - Vault orlop.VaultConfig +type ValidatorConfig struct { } -var marker = &Config{} - -func AddToContext(ctx context.Context, cfg *Config) context.Context { - return context.WithValue(ctx, marker, cfg) +type LoaderConfig struct { + AppConfigFile string + Version string + PluginFilename string + ObjectsDir string + AssetsDir string + Env map[string]string } -func GetFromContext(ctx context.Context) *Config { - if x := ctx.Value(marker); x != nil { - if v, ok := x.(*Config); ok { - return v - } - } - return nil +type PublisherConfig struct { + AccessToken string + URL string } diff --git a/flags/flags.go b/flags/flags.go index dafdba7..dde7f12 100644 --- a/flags/flags.go +++ b/flags/flags.go @@ -6,6 +6,10 @@ const ( Org = "org" AppID = "app-id" URL = "url" + Plugin = "plugin" + Objects = "objects" + Assets = "assets" + Env = "env" Version = "version" TLSInsecure = "insecure" TLSCert = "tls-cert" diff --git a/go.mod b/go.mod index fb23dfc..a0c8554 100644 --- a/go.mod +++ b/go.mod @@ -1,30 +1,23 @@ module go.ketch.com/cli/ketch-cli -go 1.15 +go 1.16 require ( - github.com/cloudevents/sdk-go/v2 v2.3.1 - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/hashicorp/go-hclog v0.14.1 // indirect + github.com/cloudevents/sdk-go/v2 v2.4.1 + github.com/ghodss/yaml v1.0.0 + github.com/gogo/protobuf v1.3.2 + github.com/jinzhu/copier v0.3.2 github.com/joho/godotenv v1.3.0 - github.com/sirupsen/logrus v1.7.0 - github.com/spf13/cobra v1.1.1 - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/sirupsen/logrus v1.8.1 + github.com/spf13/cobra v1.1.3 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.7.0 github.com/xeipuuv/gojsonschema v1.2.0 - go.ketch.com/lib/oid v1.1.0 - go.ketch.com/lib/orlop v1.35.3 - go.ketch.com/lib/webhook-client v0.2.4 - go.opencensus.io v0.22.5 // indirect - go.opentelemetry.io/otel/exporters/metric/prometheus v0.15.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.16.0 // indirect - golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 // indirect - golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect - golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 // indirect - golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f // indirect - golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect - golang.org/x/tools v0.0.0-20201208233053-a543418bbed2 // indirect - google.golang.org/genproto v0.0.0-20201211151036-40ec1c210f7a // indirect - gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 - honnef.co/go/tools v0.0.1-2020.1.6 // indirect + go.ketch.com/lib/app v0.3.0 + go.ketch.com/lib/oid v1.2.0 + go.ketch.com/lib/orlop v1.40.0 + go.ketch.com/lib/webhook-client v0.3.1 + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c ) + +replace go.ketch.com/lib/app => ../app/ diff --git a/go.sum b/go.sum index 8420238..d60b0d5 100644 --- a/go.sum +++ b/go.sum @@ -4,7 +4,6 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -15,7 +14,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/sketches-go v0.0.1 h1:RtG+76WKgZuz6FIaGsjoPePmadDBkuD/KC6+ZWu78b8= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/sketches-go v0.0.1/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -33,12 +32,13 @@ github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/benbjohnson/clock v1.0.3 h1:vkLuvpK4fmtSCuo60+yC63p7y0BmQ8gm5ZXGuBCJyXg= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -53,12 +53,16 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudevents/sdk-go/v2 v2.3.1 h1:QRTu0yRA4FbznjRSds0/4Hy6cVYpWV2wInlNJSHWAtw= github.com/cloudevents/sdk-go/v2 v2.3.1/go.mod h1:4fO2UjPMYYR1/7KPJQCwTPb0lFA8zYuitkUpAZFSY1Q= +github.com/cloudevents/sdk-go/v2 v2.4.1 h1:rZJoz9QVLbWQmnvLPDFEmv17Czu+CfSPwMO6lhJ72xQ= +github.com/cloudevents/sdk-go/v2 v2.4.1/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -89,19 +93,20 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.7.2 h1:2QxQoC1TS09S7fhCPsrvqYdvP1H5M1P1ih5ABm3BTYk= github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -109,24 +114,25 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -141,8 +147,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= @@ -155,17 +163,15 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -197,15 +203,17 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= @@ -218,6 +226,7 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -230,20 +239,24 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault/api v1.0.4 h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU= github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= -github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0sMLy8= +github.com/hashicorp/vault/api v1.1.0 h1:QcxC7FuqEl0sZaIjcXB/kNEeBa0DH5z57qbWBvZwLC4= +github.com/hashicorp/vault/api v1.1.0/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk= github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 h1:e1ok06zGrWJW91rzRroyl5nRNqraaBe4d5hiKcVZuHM= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/iancoleman/strcase v0.1.2 h1:gnomlvw9tnV3ITTAxzKSgTF+8kFWcU/f+TgttpXGz1U= github.com/iancoleman/strcase v0.1.2/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/iancoleman/strcase v0.1.3 h1:dJBk1m2/qjL1twPLf68JND55vvivMupZ4wIzE8CTdBw= +github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w= +github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= @@ -252,6 +265,7 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -259,29 +273,25 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac h1:+2b6iGRJe3hvV/yVXrd41yVEjxuFHxasJqDhkIjS4gk= github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -299,12 +309,15 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks= github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -315,7 +328,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -323,10 +335,8 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94= github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= @@ -356,13 +366,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -371,22 +383,26 @@ github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -403,8 +419,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -413,8 +430,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -425,23 +442,24 @@ github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= @@ -452,63 +470,72 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.ketch.com/lib/oid v1.1.0 h1:+64TEDFmVJNMxFGgALYZ8v1kmWM8RTAq+SgTRzsbpO8= -go.ketch.com/lib/oid v1.1.0/go.mod h1:z5Vv+db9quqyAwbk3qKmHu3DyzP2lWw2xLwFfOhBdC0= -go.ketch.com/lib/orlop v1.35.3 h1:Pc+7iqa4kWmz4CiU0NyveBENeGoDT94BleRjgas7jCE= +go.ketch.com/lib/oid v1.2.0 h1:wGFoq8feBkJWacwSk1jDH5qjmS1Hj1rk58WaPZBa3LQ= +go.ketch.com/lib/oid v1.2.0/go.mod h1:wkK6b4+nim+Cf1QDmWVa6GEPVv7xPm7qOrG9VrDkEHo= go.ketch.com/lib/orlop v1.35.3/go.mod h1:vpOFdg6GQYktDVDErcTxkbrDQT1Gz7KLjR9m5VUResc= -go.ketch.com/lib/webhook-client v0.2.4 h1:XGdPcITYArrKCxsDxuBQsznyZ512CU/DdEebC2jVBkA= -go.ketch.com/lib/webhook-client v0.2.4/go.mod h1:zQgdIRtSku8V3BZbLLE3JHQqiD5eOlrWLVyFcQncXvo= +go.ketch.com/lib/orlop v1.40.0 h1:BN9SIYi87XXQfbYa8cji0hHc5mVsglm1siQZWF2M6xA= +go.ketch.com/lib/orlop v1.40.0/go.mod h1:hMG+IdOjkEOncWevLBnWN+fG16YXG1yA1PuqZTZp8vY= +go.ketch.com/lib/webhook-client v0.3.1 h1:r5uxEfLH2R9w1CrefRO0KEFbury3MhQn9y+79KnNrOE= +go.ketch.com/lib/webhook-client v0.3.1/go.mod h1:zQgdIRtSku8V3BZbLLE3JHQqiD5eOlrWLVyFcQncXvo= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib v0.14.0 h1:ntrQmEKqYQL6z2YNCk+3Cg4lpJwd9aHK/JMOFpda8yc= go.opentelemetry.io/contrib v0.14.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.14.0 h1:/3A1Eo1aPgW/0qgcQKHC7M6AQoEtwI1aVMO6N14a98g= +go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.14.0/go.mod h1:5UKZEbbbKoWIuY4S/6tt1zHY6L5WF5wmRIDR2OfFSZQ= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.14.0 h1:f7M+R7vO1Q8hq29huD14olXE9Seor47BjPzs1p+VW38= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.14.0/go.mod h1:Rw8yZpEGuffGoRJ8yoxjvQd3qZZuWfDj163NEfux2sw= -go.opentelemetry.io/contrib/instrumentation/runtime v0.14.0 h1:CN6KOuYF+Kdvfw7QxzGV7B1B19YgnNBdd8+hpPsz3TA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= go.opentelemetry.io/contrib/instrumentation/runtime v0.14.0/go.mod h1:1Mdmr68bBZNMdEDM6VIst+QTD8YdKCvVGizkxf/93qw= +go.opentelemetry.io/contrib/instrumentation/runtime v0.20.0 h1:U47RkWj4bhBqo2pEwk0JTbyPJi5LjTamfSKQoB7bMgU= +go.opentelemetry.io/contrib/instrumentation/runtime v0.20.0/go.mod h1:l+fJcxuHSyCvPtEPTINAqR4Qm3iJ68mfACrcEPWafWg= go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw= -go.opentelemetry.io/otel v0.15.0 h1:CZFy2lPhxd4HlhZnYK8gRyDotksO3Ip9rBweY1vVYJw= -go.opentelemetry.io/otel v0.15.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= +go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel/exporters/metric/prometheus v0.14.0/go.mod h1:1YFGCWmDN9G7Wz/wTOqEU1+nrfLjc1F1hxIjtdGwjmA= -go.opentelemetry.io/otel/exporters/metric/prometheus v0.15.0 h1:QlAdmYM0BKQ9HtiL2v5P567ibwHiiaOeBXQDOq0ShZM= -go.opentelemetry.io/otel/exporters/metric/prometheus v0.15.0/go.mod h1:f9asEgpGz31ojVlnfqGl69jAcguvvSupm+L3b48QZ7Y= +go.opentelemetry.io/otel/exporters/metric/prometheus v0.20.0 h1:mJ577SMWSG1jLplCakscznQK7hK03YayX1fQkDPKoVw= +go.opentelemetry.io/otel/exporters/metric/prometheus v0.20.0/go.mod h1:XG78/f5fT5o2W4Fto/hrYzn3mbuzGQIFnb0P2AKe+s0= +go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= go.opentelemetry.io/otel/sdk v0.14.0/go.mod h1:kGO5pEMSNqSJppHAm8b73zztLxB5fgDQnD56/dl5xqE= -go.opentelemetry.io/otel/sdk v0.15.0 h1:Hf2dl1Ad9Hn03qjcAuAq51GP5Pv1SV5puIkS2nRhdd8= -go.opentelemetry.io/otel/sdk v0.15.0/go.mod h1:Qudkwgq81OcA9GYVlbyZ62wkLieeS1eWxIL0ufxgwoc= +go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc= golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 h1:sYNJzB4J8toYPQTM6pAkcmBRgw9SnQKP9oXCHfgy604= -golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -522,9 +549,8 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -553,16 +579,15 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -571,6 +596,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -602,12 +628,11 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f h1:QdHQnPce6K4XQewki9WNbG5KOROuDzqO3NaYjI1cXJ0= -golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -619,9 +644,9 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -643,13 +668,13 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2 h1:vEtypaVub6UvKkiXZ2xx9QIvp9TL7sI7xp7vdi2kezA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -665,7 +690,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -680,9 +704,8 @@ google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBr google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e h1:wYR00/Ht+i/79g/gzhdehBgLIJCklKoc8Q/NebdzzpY= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201211151036-40ec1c210f7a h1:GnJAhasbD8HiT8DZMvsEx3QLVy/X0icq/MGr0MqRJ2M= -google.golang.org/genproto v0.0.0-20201211151036-40ec1c210f7a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -699,8 +722,9 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -710,18 +734,18 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -729,7 +753,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -738,20 +761,17 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.6 h1:W18jzjh8mfPez+AwGLxmOImucz/IFjpNlrKVnaj2YVc= -honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/services/apps.go b/services/apps.go new file mode 100644 index 0000000..47104d9 --- /dev/null +++ b/services/apps.go @@ -0,0 +1,31 @@ +package services + +import ( + "context" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/lib/app" +) + +//go:generate mockery --all + +// Reporter provides an interface to report messages +type Reporter interface { + // Report a message to the user + Report(ctx context.Context, format string, args ...interface{}) +} + +// Loader provides an interface to load an App based on the specified configuration +type Loader interface { + Load(ctx context.Context, cfg *config.LoaderConfig) (*app.App, error) + LoadExternalFiles(ctx context.Context, cfg *config.LoaderConfig, manifest *app.App) error +} + +// Validator provides an interface to validate an App either in bytes form or object form +type Validator interface { + Validate(ctx context.Context, app *app.App) error +} + +// Publisher provides an interface to publish an App +type Publisher interface { + Publish(ctx context.Context, app *app.App) error +} diff --git a/services/impl/loader.go b/services/impl/loader.go new file mode 100644 index 0000000..fa7347d --- /dev/null +++ b/services/impl/loader.go @@ -0,0 +1,372 @@ +package impl + +import ( + "bytes" + "context" + "encoding/json" + "github.com/gogo/protobuf/jsonpb" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/cli/ketch-cli/services" + "go.ketch.com/cli/ketch-cli/utils" + "go.ketch.com/lib/app" + "go.ketch.com/lib/orlop/errors" + "io/fs" + "io/ioutil" + "mime" + "net/http" + "net/url" + "os" + "path" + "path/filepath" + "strings" +) + +const ( + currentVersion = app.CurrentVersion + defaultPlugin = "plugin/plugin.js" + defaultObjectsDir = "objects/" + defaultAssetsDir = "assets/" +) + +type loader struct { + reporter services.Reporter + client *http.Client +} + +func NewLoader(reporter services.Reporter, client *http.Client) services.Loader { + return &loader{ + reporter: reporter, + client: client, + } +} + +func (l *loader) Load(ctx context.Context, cfg *config.LoaderConfig) (*app.App, error) { + var err error + + l.reporter.Report(ctx, "resolving inputs") + if stat, err := os.Stat(cfg.AppConfigFile); err != nil || stat.IsDir() { + return nil, errors.Errorf("file '%s' does not exist", cfg.AppConfigFile) + } + + cfg.AppConfigFile, err = filepath.Abs(cfg.AppConfigFile) + if err != nil { + return nil, err + } + + basePath := filepath.Dir(cfg.AppConfigFile) + + wd, err := os.Getwd() + if err != nil { + return nil, err + } + + if err = os.Chdir(basePath); err != nil { + return nil, err + } + + defer func() { + os.Chdir(wd) + }() + + if len(cfg.PluginFilename) > 0 { + if stat, err := os.Stat(cfg.PluginFilename); err != nil || stat.IsDir() { + return nil, errors.Errorf("plugin file '%s' does not exist", cfg.PluginFilename) + } + } else if stat, err := os.Stat(defaultPlugin); err == nil && !stat.IsDir() { + cfg.PluginFilename = defaultPlugin + } + + if len(cfg.PluginFilename) > 0 { + cfg.PluginFilename, err = filepath.Abs(cfg.PluginFilename) + if err != nil { + return nil, err + } + } + + if len(cfg.ObjectsDir) > 0 { + if stat, err := os.Stat(cfg.ObjectsDir); err != nil || !stat.IsDir() { + return nil, errors.Errorf("objects directory '%s' does not exist", cfg.ObjectsDir) + } + } else if stat, err := os.Stat(defaultObjectsDir); err == nil && stat.IsDir() { + cfg.ObjectsDir = defaultObjectsDir + } + + if len(cfg.ObjectsDir) > 0 { + cfg.ObjectsDir, err = filepath.Abs(cfg.ObjectsDir) + if err != nil { + return nil, err + } + } + + if len(cfg.AssetsDir) > 0 { + if stat, err := os.Stat(cfg.AssetsDir); err != nil || !stat.IsDir() { + return nil, errors.Errorf("assets directory '%s' does not exist", cfg.AssetsDir) + } + } else if stat, err := os.Stat(defaultAssetsDir); err == nil && stat.IsDir() { + cfg.AssetsDir = defaultAssetsDir + } + + if len(cfg.AssetsDir) > 0 { + cfg.AssetsDir, err = filepath.Abs(cfg.AssetsDir) + if err != nil { + return nil, err + } + } + + l.reporter.Report(ctx, "loading '%s'...", cfg.AppConfigFile) + + b, err := ioutil.ReadFile(cfg.AppConfigFile) + if err != nil { + return nil, err + } + + if len(cfg.Env) > 0 { + b = []byte(os.Expand(string(b), func(s string) string { + return cfg.Env[s] + })) + } + + b = []byte(os.ExpandEnv(string(b))) + + manifest := &app.App{} + + if len(b) > 0 { + if filepath.Ext(cfg.AppConfigFile) == ".yaml" || filepath.Ext(cfg.AppConfigFile) == ".yml" { + b, err = utils.YAMLtoJSON(b) + if err != nil { + return nil, err + } + } + + if err = json.Unmarshal(b, manifest); err != nil { + return nil, err + } + } + + if manifest.ApiVersion != currentVersion { + return nil, errors.Errorf("apiVersion '%s' is invalid (expected '%s')", manifest.ApiVersion, currentVersion) + } + + if manifest.Kind != "App" { + return nil, errors.Errorf("kind '%s' is invalid (expected 'App')", manifest.Kind) + } + + if manifest.Metadata == nil { + return nil, errors.New("metadata is required") + } + + if manifest.Data == nil { + return nil, errors.New("data is required") + } + + if len(cfg.Version) > 0 { + manifest.Data.Version = cfg.Version + } + + if len(manifest.Data.Version) == 0 { + return nil, errors.New("app version must be specified in file or via --version") + } + return manifest, nil +} + +func (l *loader) LoadExternalFiles(ctx context.Context, cfg *config.LoaderConfig, manifest *app.App) error { + var err error + + basePath := filepath.Dir(cfg.AppConfigFile) + + wd, err := os.Getwd() + if err != nil { + return err + } + + if err = os.Chdir(basePath); err != nil { + return err + } + + defer func() { + os.Chdir(wd) + }() + + if len(cfg.PluginFilename) > 0 { + manifest.Data.Assets = append(manifest.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Link: cfg.PluginFilename, + Name: filepath.Base(cfg.PluginFilename), + }) + } + + // Add custom objects + if len(cfg.ObjectsDir) > 0 { + l.reporter.Report(ctx, "loading objects...") + + err = filepath.WalkDir(cfg.ObjectsDir, func(path string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() { + return err + } + + relativePath := strings.TrimPrefix(path, cfg.ObjectsDir+"/") + + b, err := os.ReadFile(path) + if err != nil { + return err + } + + if filepath.Ext(path) == ".yaml" || filepath.Ext(path) == ".yml" { + b, err = utils.YAMLtoJSON(b) + if err != nil { + return err + } + } + + if len(b) == 0 { + return errors.Errorf("custom object '%s' is empty", relativePath) + } + + obj := &app.AppObject{} + if err = jsonpb.Unmarshal(bytes.NewReader(b), obj); err != nil { + return err + } + + if obj.ApiVersion != currentVersion { + return errors.Errorf("custom object '%s' is invalid - apiVersion must be '%s'", relativePath, currentVersion) + } + + if len(obj.Kind) == 0 { + return errors.Errorf("custom object '%s' is invalid - kind is empty", relativePath) + } + + if obj.Metadata == nil { + return errors.Errorf("custom object '%s' is invalid - metadata is empty", relativePath) + } + + if obj.Data == nil { + return errors.Errorf("custom object '%s' is invalid - data is empty", relativePath) + } + + manifest.Data.CustomObjects = append(manifest.Data.CustomObjects, obj) + return nil + }) + if err != nil { + return err + } + } + + if manifest.Data.Logo != nil { + l.reporter.Report(ctx, "loading logo...") + + if manifest.Data.Logo, err = l.loadImage(ctx, manifest.Data.Logo); err != nil { + return err + } + } + + if len(manifest.Data.Previews) > 0 { + l.reporter.Report(ctx, "loading previews...") + for n := range manifest.Data.Previews { + if manifest.Data.Previews[n], err = l.loadImage(ctx, manifest.Data.Previews[n]); err != nil { + return err + } + } + } + + if len(cfg.AssetsDir) > 0 { + l.reporter.Report(ctx, "loading assets...") + err = filepath.WalkDir(cfg.AssetsDir, func(path string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() { + return err + } + + manifest.Data.Assets = append(manifest.Data.Assets, &app.AppAsset{ + Link: path, + Name: strings.TrimPrefix(path, cfg.AssetsDir+"/"), + }) + return nil + }) + if err != nil { + return err + } + } + + for n := range manifest.Data.Assets { + if manifest.Data.Assets[n], err = l.loadAsset(ctx, manifest.Data.Assets[n]); err != nil { + return err + } + } + + return nil +} + +func (l *loader) loadImage(ctx context.Context, in *app.AppImage) (*app.AppImage, error) { + var err error + + in.ContentType = mime.TypeByExtension(path.Ext(in.Link)) + + if in.Contents, err = l.getFileData(ctx, in.Link); err != nil { + return nil, err + } + + in.Link = "" + + return in, nil +} + +func (l *loader) loadAsset(ctx context.Context, in *app.AppAsset) (*app.AppAsset, error) { + var err error + + in.ContentType = mime.TypeByExtension(path.Ext(in.Link)) + + if in.Contents, err = l.getFileData(ctx, in.Link); err != nil { + return nil, err + } + + in.Link = "" + + return in, nil +} + +func (l *loader) getFileData(ctx context.Context, link string) (b []byte, err error) { + l.reporter.Report(ctx, "loading %s...", link) + + if l.isRemoteLink(link) { + b, err = l.getRemoteFileData(ctx, link) + } else { + b, err = l.getLocalFileData(ctx, link) + } + if err != nil { + return nil, err + } + + return +} + +func (l *loader) getRemoteFileData(ctx context.Context, url string) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + resp, err := l.client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + return ioutil.ReadAll(resp.Body) +} + +func (l *loader) getLocalFileData(ctx context.Context, link string) ([]byte, error) { + return ioutil.ReadFile(link) +} + +func (l *loader) isRemoteLink(link string) bool { + _, err := url.ParseRequestURI(link) + if err != nil { + return false + } + + u, err := url.Parse(link) + if err != nil || u.Scheme == "" || u.Host == "" { + return false + } + + return true +} diff --git a/services/impl/loader_test.go b/services/impl/loader_test.go new file mode 100644 index 0000000..a5dc8e3 --- /dev/null +++ b/services/impl/loader_test.go @@ -0,0 +1,563 @@ +package impl + +import ( + "context" + "fmt" + "github.com/gogo/protobuf/types" + "github.com/jinzhu/copier" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/lib/app" + "go.ketch.com/lib/orlop/errors" + "testing" +) + +func copyApp(in app.App, modify func(*app.App)) app.App { + var out app.App + copier.Copy(&out, &in) + modify(&out) + return out +} + +func TestLoad(t *testing.T) { + ctx := context.Background() + + for _, testCase := range []struct { + Name string + Config *config.LoaderConfig + Error error + Expected app.App + }{ + { + Name: "fixture1", + Config: &config.LoaderConfig{}, + Error: errors.New("apiVersion '' is invalid (expected 'v1')"), + }, + { + Name: "fixture2", + Config: &config.LoaderConfig{}, + Error: errors.New("kind '' is invalid (expected 'App')"), + }, + { + Name: "fixture3", + Config: &config.LoaderConfig{}, + Error: errors.New("metadata is required"), + }, + { + Name: "fixture4", + Config: &config.LoaderConfig{}, + Error: errors.New("metadata is required"), + }, + { + Name: "fixture5", + Config: &config.LoaderConfig{}, + Error: errors.New("data is required"), + }, + { + Name: "fixture6", + Config: &config.LoaderConfig{}, + Error: nil, + }, + { + Name: "fixture7", + Config: &config.LoaderConfig{}, + Expected: app.App{ + ApiVersion: "v1", + Kind: "App", + Metadata: &app.AppMetadata{ + Code: "fixture", + Name: "Fixture", + }, + Data: &app.AppData{ + Version: "0.0.0", + PrimaryCategory: "privacy", + }, + }, + }, + { + Name: "fixture8", + Config: &config.LoaderConfig{}, + Expected: app.App{ + ApiVersion: "v1", + Kind: "App", + Metadata: &app.AppMetadata{ + Code: "fixture", + Name: "Fixture", + Description: "Fixture description", + }, + Data: &app.AppData{ + Version: "0.0.0", + PrimaryCategory: "privacy", + }, + }, + }, + { + Name: "fixture9", + Config: &config.LoaderConfig{}, + Expected: app.App{ + ApiVersion: "v1", + Kind: "App", + Metadata: &app.AppMetadata{ + Code: "fixture", + Name: "Fixture", + Description: "Fixture description", + }, + Data: &app.AppData{ + Version: "0.0.0", + PrimaryCategory: "privacy", + SecondaryCategory: "privacy", + }, + }, + }, + } { + t.Run(testCase.Name, func(t *testing.T) { + p := NewLoader(NewNilReporter(), nil) + + testCase.Config.Version = "0.0.0" + testCase.Config.AppConfigFile = fmt.Sprintf("../../test/fixtures/%s/ketch-manifest.yaml", testCase.Name) + + actual, err := p.Load(ctx, testCase.Config) + if testCase.Error == nil { + require.NoError(t, err) + } else if err == nil { + require.Error(t, err) + } else { + require.EqualError(t, err, testCase.Error.Error()) + } + + if testCase.Expected.ApiVersion != "" { + assert.EqualValues(t, testCase.Expected, *actual) + } + }) + } +} + +func TestLoadExternalFiles(t *testing.T) { + ctx := context.Background() + + baseApp := app.App{ + ApiVersion: "v1", + Kind: "App", + Metadata: &app.AppMetadata{ + Code: "fixture", + Name: "Fixture", + Description: "Fixture description", + }, + Data: &app.AppData{ + AutoUpgrade: true, + Capabilities: []string{"permitPropagation"}, + Contacts: []*app.AppContact{ + { + Email: "technical@example.com", + Name: "Technical", + Type: "technical", + }, + }, + CustomerSupportURL: "https://support", + Depends: "a, b, c", + DetailedDescription: "detailed desc", + DocURL: "https://docs", + ExpireUserTokens: true, + Form: []*app.FormComponent{ + { + Data: nil, + Default: "", + Description: "", + Editable: false, + MaxLength: 0, + MinLength: 0, + Multiple: false, + Name: "input", + Pattern: "", + Placeholder: "", + Required: false, + ShowOnView: false, + ShowValueOnEdit: false, + Spellcheck: false, + Type: "string", + }, + }, + HomepageURL: "https://homepage", + IdentitySpaces: []*app.IdentitySpace{ + { + Linked: &app.ReferencedIdentitySpace{ + Code: "linked", + Description: "linked identity", + Filters: []*app.IdentitySpaceFilter{ + { + Format: "raw", + Type: "ios_advertising_id", + }, + }, + Name: "linked idfa", + }, + }, + { + Managed: &app.ManagedIdentitySpace{ + Code: "managed", + Description: "managed identity", + Format: "raw", + Name: "managed aaid", + Type: "android_advertising_id", + Variable: &app.IdentitySpaceVariable{ + Jwt: &app.IdentitySpaceVariableJwt{ + Key: "key", + Location: "claims", + }, + Location: "cookie", + Name: "myjwt", + }, + }, + }, + }, + InfoURL: "https://info", + Instances: "single", + Logo: &app.AppImage{ + Code: "logo", + ContentType: "image/png", + Height: 234, + Title: "Logo", + Width: 345, + Contents: []byte{}, + }, + Permissions: []string{"scope1"}, + Previews: []*app.AppImage{ + { + Code: "preview", + ContentType: "image/png", + Height: 123, + Title: "Preview 1", + Width: 456, + Contents: []byte{}, + }, + }, + PrimaryCategory: "privacy", + PrivacyPolicyURL: "https://privacy", + Provides: []string{ + "sku1", + "sku2", + }, + RedirectOnUpdate: true, + RefreshInterval: "2h", + RequestUserAuth: true, + Rules: &app.AppDataRules{ + Install: "to install", + View: "to view", + }, + SecondaryCategory: "privacy", + SetupURL: "https://setup", + ShortDescription: "short description", + StatusURL: "https://status", + SupportedLanguages: []string{"en"}, + SupportedPurposes: []string{"analytics"}, + SupportedRights: []string{"delete"}, + TosURL: "https://tos", + Type: "custom", + UserAuthCallbackURL: "https://auth", + Version: "0.0.0", + Webhook: &app.Webhook{ + Events: []string{"ping"}, + MaxQPS: 0, + Tls: &app.WebhookTls{ + Insecure: true, + }, + Url: "https://webhook", + Secret: []byte{}, + }, + Assets: []*app.AppAsset{}, + CustomObjects: []*app.AppObject{}, + }, + } + + for _, testCase := range []struct { + Name string + Config *config.LoaderConfig + Error error + Expected app.App + }{ + { + Name: "fixture10", + Config: &config.LoaderConfig{}, + Error: errors.New("open images/logo.png: no such file or directory"), + }, + { + Name: "fixture11", + Config: &config.LoaderConfig{}, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + }), + }, + { + Name: "fixture12", + Config: &config.LoaderConfig{}, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Contents: []byte("alert(1);\n"), + Name: "plugin.js", + }) + }), + }, + { + Name: "fixture13", + Config: &config.LoaderConfig{}, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Contents: []byte("alert(1);\n"), + Name: "plugin.js", + }) + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "image/png", + Name: "image.png", + Contents: []byte("image\n"), + }) + }), + }, + { + Name: "fixture14", + Config: &config.LoaderConfig{}, + Error: errors.New("custom object 'legalBasis1.yaml' is empty"), + }, + { + Name: "fixture15", + Config: &config.LoaderConfig{}, + Error: errors.New("custom object 'legalBasis1.yaml' is invalid - apiVersion must be 'v1'"), + }, + { + Name: "fixture16", + Config: &config.LoaderConfig{}, + Error: errors.New("custom object 'legalBasis1.yaml' is invalid - kind is empty"), + }, + { + Name: "fixture17", + Config: &config.LoaderConfig{}, + Error: errors.New("custom object 'legalBasis1.yaml' is invalid - metadata is empty"), + }, + { + Name: "fixture18", + Config: &config.LoaderConfig{}, + Error: errors.New("custom object 'legalBasis1.yaml' is invalid - data is empty"), + }, + { + Name: "fixture19", + Config: &config.LoaderConfig{}, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Contents: []byte("alert(1);\n"), + Name: "plugin.js", + }) + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "image/png", + Name: "image.png", + Contents: []byte("image\n"), + }) + a.Data.CustomObjects = append(a.Data.CustomObjects, &app.AppObject{ + ApiVersion: "v1", + Kind: "LegalBasis", + Metadata: &app.AppMetadata{ + Code: "disclosure", + Name: "Disclosure", + }, + Data: &types.Struct{ + Fields: map[string]*types.Value{ + "requiresOptIn": { + Kind: &types.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + }, + }) + }), + }, + { + Name: "fixture20", + Config: &config.LoaderConfig{ + PluginFilename: "alt_plugin/plugin.js", + }, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Contents: []byte("alert(1);\n"), + Name: "plugin.js", + }) + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "image/png", + Name: "image.png", + Contents: []byte("image\n"), + }) + a.Data.CustomObjects = append(a.Data.CustomObjects, &app.AppObject{ + ApiVersion: "v1", + Kind: "LegalBasis", + Metadata: &app.AppMetadata{ + Code: "disclosure", + Name: "Disclosure", + }, + Data: &types.Struct{ + Fields: map[string]*types.Value{ + "requiresOptIn": { + Kind: &types.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + }, + }) + }), + }, + { + Name: "fixture21", + Config: &config.LoaderConfig{ + PluginFilename: "alt_plugin/plugin.js", + AssetsDir: "alt_assets", + }, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Contents: []byte("alert(1);\n"), + Name: "plugin.js", + }) + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "image/png", + Name: "image.png", + Contents: []byte("image\n"), + }) + a.Data.CustomObjects = append(a.Data.CustomObjects, &app.AppObject{ + ApiVersion: "v1", + Kind: "LegalBasis", + Metadata: &app.AppMetadata{ + Code: "disclosure", + Name: "Disclosure", + }, + Data: &types.Struct{ + Fields: map[string]*types.Value{ + "requiresOptIn": { + Kind: &types.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + }, + }) + }), + }, + { + Name: "fixture22", + Config: &config.LoaderConfig{ + PluginFilename: "alt_plugin/plugin.js", + AssetsDir: "alt_assets", + ObjectsDir: "alt_objects", + }, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Contents: []byte("alert(1);\n"), + Name: "plugin.js", + }) + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "image/png", + Name: "image.png", + Contents: []byte("image\n"), + }) + a.Data.CustomObjects = append(a.Data.CustomObjects, &app.AppObject{ + ApiVersion: "v1", + Kind: "LegalBasis", + Metadata: &app.AppMetadata{ + Code: "disclosure", + Name: "Disclosure", + }, + Data: &types.Struct{ + Fields: map[string]*types.Value{ + "requiresOptIn": { + Kind: &types.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + }, + }) + }), + }, + { + Name: "fixture23", + Config: &config.LoaderConfig{ + PluginFilename: "alt_plugin/plugin.js", + AssetsDir: "alt_assets", + ObjectsDir: "alt_objects", + Env: map[string]string{ + "APP_NAME": "Fixture", + }, + }, + Expected: copyApp(baseApp, func(a *app.App) { + a.Data.Logo.Contents = []byte("logo\n") + a.Data.Previews[0].Contents = []byte("preview1\n") + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "application/javascript", + Contents: []byte("alert(1);\n"), + Name: "plugin.js", + }) + a.Data.Assets = append(a.Data.Assets, &app.AppAsset{ + ContentType: "image/png", + Name: "image.png", + Contents: []byte("image\n"), + }) + a.Data.CustomObjects = append(a.Data.CustomObjects, &app.AppObject{ + ApiVersion: "v1", + Kind: "LegalBasis", + Metadata: &app.AppMetadata{ + Code: "disclosure", + Name: "Disclosure", + }, + Data: &types.Struct{ + Fields: map[string]*types.Value{ + "requiresOptIn": { + Kind: &types.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + }, + }) + }), + }, + } { + t.Run(testCase.Name, func(t *testing.T) { + p := NewLoader(NewNilReporter(), nil) + + testCase.Config.Version = "0.0.0" + testCase.Config.AppConfigFile = fmt.Sprintf("../../test/fixtures/%s/ketch-manifest.yaml", testCase.Name) + + actual, err := p.Load(ctx, testCase.Config) + require.NoError(t, err) + + err = p.LoadExternalFiles(ctx, testCase.Config, actual) + if testCase.Error == nil { + require.NoError(t, err) + } else if err == nil { + require.Error(t, err) + } else { + require.EqualError(t, err, testCase.Error.Error()) + } + + if testCase.Expected.ApiVersion != "" { + assert.EqualValues(t, testCase.Expected, *actual) + } + }) + } +} diff --git a/services/impl/publisher.go b/services/impl/publisher.go new file mode 100644 index 0000000..e8ec41c --- /dev/null +++ b/services/impl/publisher.go @@ -0,0 +1,31 @@ +package impl + +import ( + "context" + "encoding/json" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/cli/ketch-cli/services" + "go.ketch.com/lib/app" + "go.ketch.com/lib/orlop/errors" + "os" +) + +type publisher struct { + cfg *config.PublisherConfig +} + +func NewPublisher(cfg *config.PublisherConfig) services.Publisher { + return &publisher{ + cfg: cfg, + } +} + +func (p *publisher) Publish(ctx context.Context, app *app.App) error { + en := json.NewEncoder(os.Stdout) + en.SetIndent("", " ") + if err := en.Encode(app); err != nil { + return err + } + + return errors.New("implement me") +} diff --git a/services/impl/publisher_test.go b/services/impl/publisher_test.go new file mode 100644 index 0000000..d5159fa --- /dev/null +++ b/services/impl/publisher_test.go @@ -0,0 +1,24 @@ +package impl + +import ( + "context" + "github.com/stretchr/testify/assert" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/lib/app" + "testing" +) + +func TestPublish(t *testing.T) { + ctx := context.Background() + + cfg := &config.PublisherConfig{ + AccessToken: "", + URL: "", + } + + manifest := &app.App{} + + p := NewPublisher(cfg) + err := p.Publish(ctx, manifest) + assert.NoError(t, err) +} diff --git a/services/impl/reporter.go b/services/impl/reporter.go new file mode 100644 index 0000000..fffaad7 --- /dev/null +++ b/services/impl/reporter.go @@ -0,0 +1,25 @@ +package impl + +import ( + "context" + "fmt" + "go.ketch.com/cli/ketch-cli/services" +) + +type reporter struct{} + +func NewReporter() services.Reporter { + return &reporter{} +} + +func (reporter) Report(ctx context.Context, format string, args ...interface{}) { + fmt.Println(fmt.Sprintf(format, args...)) +} + +type nilReporter struct{} + +func NewNilReporter() services.Reporter { + return &nilReporter{} +} + +func (nilReporter) Report(ctx context.Context, format string, args ...interface{}) {} diff --git a/services/impl/validator.go b/services/impl/validator.go new file mode 100644 index 0000000..5d44023 --- /dev/null +++ b/services/impl/validator.go @@ -0,0 +1,48 @@ +package impl + +import ( + "context" + "github.com/xeipuuv/gojsonschema" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/cli/ketch-cli/services" + "go.ketch.com/lib/app" + "go.ketch.com/lib/orlop/errors" +) + +type validator struct { + cfg *config.ValidatorConfig + reporter services.Reporter +} + +func NewValidator(cfg *config.ValidatorConfig, reporter services.Reporter) services.Validator { + return &validator{ + cfg: cfg, + reporter: reporter, + } +} + +func (v *validator) Validate(ctx context.Context, app *app.App) error { + return v.validate(ctx, gojsonschema.NewGoLoader(app)) +} + +func (v *validator) validate(ctx context.Context, appConfigLoader gojsonschema.JSONLoader) error { + manifestSchema, err := app.JSONSchema() + if err != nil { + return err + } + + result, err := gojsonschema.Validate(gojsonschema.NewBytesLoader(manifestSchema), appConfigLoader) + if err != nil { + return err + } + + if !result.Valid() { + for _, resultError := range result.Errors() { + v.reporter.Report(ctx, resultError.String()) + } + + return errors.New("app config invalid") + } + + return nil +} diff --git a/services/impl/validator_test.go b/services/impl/validator_test.go new file mode 100644 index 0000000..6747797 --- /dev/null +++ b/services/impl/validator_test.go @@ -0,0 +1,97 @@ +package impl + +import ( + "context" + "encoding/json" + "fmt" + "github.com/stretchr/testify/require" + "go.ketch.com/cli/ketch-cli/config" + "go.ketch.com/cli/ketch-cli/utils" + "go.ketch.com/lib/app" + "go.ketch.com/lib/orlop/errors" + "os" + "testing" +) + +func TestValidate(t *testing.T) { + ctx := context.Background() + + cfg := &config.ValidatorConfig{} + + p := NewValidator(cfg, NewReporter()) + + for _, testCase := range []struct { + Name string + Error error + }{ + { + Name: "fixture2", + Error: nil, + }, + { + Name: "fixture3", + Error: nil, + }, + { + Name: "fixture4", + Error: nil, + }, + { + Name: "fixture5", + Error: errors.New("app config invalid"), + }, + { + Name: "fixture6", + Error: errors.New("app config invalid"), + }, + { + Name: "fixture7", + Error: nil, + }, + { + Name: "fixture8", + Error: nil, + }, + { + Name: "fixture9", + Error: nil, + }, + { + Name: "fixture10", + Error: errors.New("app config invalid"), + }, + { + Name: "fixture11", + Error: nil, + }, + { + Name: "fixture12", + Error: nil, + }, + { + Name: "fixture13", + Error: nil, + }, + } { + t.Run(testCase.Name, func(t *testing.T) { + b, err := os.ReadFile(fmt.Sprintf("../../test/fixtures/%s/ketch-manifest.yaml", testCase.Name)) + require.NoError(t, err) + + manifest := &app.App{} + b, err = utils.YAMLtoJSON(b) + require.NoError(t, err) + + err = json.Unmarshal(b, &manifest) + require.NoError(t, err) + + err = p.Validate(ctx, manifest) + if testCase.Error == nil { + require.NoError(t, err) + } else if err == nil { + require.Error(t, err) + } else { + require.EqualError(t, err, testCase.Error.Error()) + } + }) + } +} diff --git a/services/mocks/Loader.go b/services/mocks/Loader.go new file mode 100644 index 0000000..f382df2 --- /dev/null +++ b/services/mocks/Loader.go @@ -0,0 +1,54 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import ( + context "context" + + config "go.ketch.com/cli/ketch-cli/config" + app "go.ketch.com/lib/app" + + mock "github.com/stretchr/testify/mock" +) + +// Loader is an autogenerated mock type for the Loader type +type Loader struct { + mock.Mock +} + +// Load provides a mock function with given fields: ctx, cfg +func (_m *Loader) Load(ctx context.Context, cfg *config.LoaderConfig) (*app.App, error) { + ret := _m.Called(ctx, cfg) + + var r0 *app.App + if rf, ok := ret.Get(0).(func(context.Context, *config.LoaderConfig) *app.App); ok { + r0 = rf(ctx, cfg) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*app.App) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *config.LoaderConfig) error); ok { + r1 = rf(ctx, cfg) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LoadExternalFiles provides a mock function with given fields: ctx, cfg, manifest +func (_m *Loader) LoadExternalFiles(ctx context.Context, cfg *config.LoaderConfig, manifest *app.App) error { + ret := _m.Called(ctx, cfg, manifest) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *config.LoaderConfig, *app.App) error); ok { + r0 = rf(ctx, cfg, manifest) + } else { + r0 = ret.Error(0) + } + + return r0 +} diff --git a/services/mocks/Publisher.go b/services/mocks/Publisher.go new file mode 100644 index 0000000..1d1f496 --- /dev/null +++ b/services/mocks/Publisher.go @@ -0,0 +1,30 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import ( + context "context" + + app "go.ketch.com/lib/app" + + mock "github.com/stretchr/testify/mock" +) + +// Publisher is an autogenerated mock type for the Publisher type +type Publisher struct { + mock.Mock +} + +// Publish provides a mock function with given fields: ctx, _a1 +func (_m *Publisher) Publish(ctx context.Context, _a1 *app.App) error { + ret := _m.Called(ctx, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *app.App) error); ok { + r0 = rf(ctx, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} diff --git a/services/mocks/Reporter.go b/services/mocks/Reporter.go new file mode 100644 index 0000000..6108385 --- /dev/null +++ b/services/mocks/Reporter.go @@ -0,0 +1,22 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// Reporter is an autogenerated mock type for the Reporter type +type Reporter struct { + mock.Mock +} + +// Report provides a mock function with given fields: ctx, format, args +func (_m *Reporter) Report(ctx context.Context, format string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, ctx, format) + _ca = append(_ca, args...) + _m.Called(_ca...) +} diff --git a/services/mocks/Validator.go b/services/mocks/Validator.go new file mode 100644 index 0000000..26a208e --- /dev/null +++ b/services/mocks/Validator.go @@ -0,0 +1,44 @@ +// Code generated by mockery 2.7.5. DO NOT EDIT. + +package mocks + +import ( + context "context" + + app "go.ketch.com/lib/app" + + mock "github.com/stretchr/testify/mock" +) + +// Validator is an autogenerated mock type for the Validator type +type Validator struct { + mock.Mock +} + +// ValidateApp provides a mock function with given fields: ctx, _a1 +func (_m *Validator) ValidateApp(ctx context.Context, _a1 *app.App) error { + ret := _m.Called(ctx, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *app.App) error); ok { + r0 = rf(ctx, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ValidateBytes provides a mock function with given fields: ctx, b +func (_m *Validator) ValidateBytes(ctx context.Context, b []byte) error { + ret := _m.Called(ctx, b) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []byte) error); ok { + r0 = rf(ctx, b) + } else { + r0 = ret.Error(0) + } + + return r0 +} diff --git a/test/fixtures/fixture1/ketch-manifest.yaml b/test/fixtures/fixture1/ketch-manifest.yaml new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/fixture10/ketch-manifest.yaml b/test/fixtures/fixture10/ketch-manifest.yaml new file mode 100644 index 0000000..8efbcb1 --- /dev/null +++ b/test/fixtures/fixture10/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - capability + contacts: + - email: support@example.com + name: Support + type: support + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: idfa + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: aaid + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - erasure + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - permit + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture11/images/logo.png b/test/fixtures/fixture11/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture11/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture11/images/preview1.png b/test/fixtures/fixture11/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture11/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture11/ketch-manifest.yaml b/test/fixtures/fixture11/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture11/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture12/images/logo.png b/test/fixtures/fixture12/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture12/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture12/images/preview1.png b/test/fixtures/fixture12/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture12/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture12/ketch-manifest.yaml b/test/fixtures/fixture12/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture12/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture12/plugin/plugin.js b/test/fixtures/fixture12/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture12/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture13/assets/image.png b/test/fixtures/fixture13/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture13/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture13/images/logo.png b/test/fixtures/fixture13/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture13/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture13/images/preview1.png b/test/fixtures/fixture13/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture13/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture13/ketch-manifest.yaml b/test/fixtures/fixture13/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture13/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture13/plugin/plugin.js b/test/fixtures/fixture13/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture13/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture14/assets/image.png b/test/fixtures/fixture14/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture14/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture14/images/logo.png b/test/fixtures/fixture14/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture14/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture14/images/preview1.png b/test/fixtures/fixture14/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture14/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture14/ketch-manifest.yaml b/test/fixtures/fixture14/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture14/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture14/objects/legalBasis1.yaml b/test/fixtures/fixture14/objects/legalBasis1.yaml new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/fixture14/plugin/plugin.js b/test/fixtures/fixture14/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture14/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture15/assets/image.png b/test/fixtures/fixture15/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture15/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture15/images/logo.png b/test/fixtures/fixture15/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture15/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture15/images/preview1.png b/test/fixtures/fixture15/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture15/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture15/ketch-manifest.yaml b/test/fixtures/fixture15/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture15/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture15/objects/legalBasis1.yaml b/test/fixtures/fixture15/objects/legalBasis1.yaml new file mode 100644 index 0000000..20197a3 --- /dev/null +++ b/test/fixtures/fixture15/objects/legalBasis1.yaml @@ -0,0 +1 @@ +apiVersion: v1alpha diff --git a/test/fixtures/fixture15/plugin/plugin.js b/test/fixtures/fixture15/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture15/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture16/assets/image.png b/test/fixtures/fixture16/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture16/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture16/images/logo.png b/test/fixtures/fixture16/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture16/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture16/images/preview1.png b/test/fixtures/fixture16/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture16/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture16/ketch-manifest.yaml b/test/fixtures/fixture16/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture16/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture16/objects/legalBasis1.yaml b/test/fixtures/fixture16/objects/legalBasis1.yaml new file mode 100644 index 0000000..9cde8e8 --- /dev/null +++ b/test/fixtures/fixture16/objects/legalBasis1.yaml @@ -0,0 +1 @@ +apiVersion: v1 diff --git a/test/fixtures/fixture16/plugin/plugin.js b/test/fixtures/fixture16/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture16/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture17/assets/image.png b/test/fixtures/fixture17/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture17/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture17/images/logo.png b/test/fixtures/fixture17/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture17/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture17/images/preview1.png b/test/fixtures/fixture17/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture17/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture17/ketch-manifest.yaml b/test/fixtures/fixture17/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture17/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture17/objects/legalBasis1.yaml b/test/fixtures/fixture17/objects/legalBasis1.yaml new file mode 100644 index 0000000..bacfea1 --- /dev/null +++ b/test/fixtures/fixture17/objects/legalBasis1.yaml @@ -0,0 +1,2 @@ +apiVersion: v1 +kind: LegalBasis diff --git a/test/fixtures/fixture17/plugin/plugin.js b/test/fixtures/fixture17/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture17/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture18/assets/image.png b/test/fixtures/fixture18/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture18/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture18/images/logo.png b/test/fixtures/fixture18/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture18/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture18/images/preview1.png b/test/fixtures/fixture18/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture18/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture18/ketch-manifest.yaml b/test/fixtures/fixture18/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture18/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture18/objects/legalBasis1.yaml b/test/fixtures/fixture18/objects/legalBasis1.yaml new file mode 100644 index 0000000..9b620e6 --- /dev/null +++ b/test/fixtures/fixture18/objects/legalBasis1.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: LegalBasis +metadata: + code: disclosure + name: Disclosure diff --git a/test/fixtures/fixture18/plugin/plugin.js b/test/fixtures/fixture18/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture18/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture19/assets/image.png b/test/fixtures/fixture19/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture19/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture19/images/logo.png b/test/fixtures/fixture19/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture19/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture19/images/preview1.png b/test/fixtures/fixture19/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture19/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture19/ketch-manifest.yaml b/test/fixtures/fixture19/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture19/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture19/objects/legalBasis1.yaml b/test/fixtures/fixture19/objects/legalBasis1.yaml new file mode 100644 index 0000000..5aeefad --- /dev/null +++ b/test/fixtures/fixture19/objects/legalBasis1.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: LegalBasis +metadata: + code: disclosure + name: Disclosure +data: + requiresOptIn: true diff --git a/test/fixtures/fixture19/plugin/plugin.js b/test/fixtures/fixture19/plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture19/plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture2/ketch-manifest.yaml b/test/fixtures/fixture2/ketch-manifest.yaml new file mode 100644 index 0000000..9cde8e8 --- /dev/null +++ b/test/fixtures/fixture2/ketch-manifest.yaml @@ -0,0 +1 @@ +apiVersion: v1 diff --git a/test/fixtures/fixture20/alt_plugin/plugin.js b/test/fixtures/fixture20/alt_plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture20/alt_plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture20/assets/image.png b/test/fixtures/fixture20/assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture20/assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture20/images/logo.png b/test/fixtures/fixture20/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture20/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture20/images/preview1.png b/test/fixtures/fixture20/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture20/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture20/ketch-manifest.yaml b/test/fixtures/fixture20/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture20/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture20/objects/legalBasis1.yaml b/test/fixtures/fixture20/objects/legalBasis1.yaml new file mode 100644 index 0000000..5aeefad --- /dev/null +++ b/test/fixtures/fixture20/objects/legalBasis1.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: LegalBasis +metadata: + code: disclosure + name: Disclosure +data: + requiresOptIn: true diff --git a/test/fixtures/fixture21/alt_assets/image.png b/test/fixtures/fixture21/alt_assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture21/alt_assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture21/alt_plugin/plugin.js b/test/fixtures/fixture21/alt_plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture21/alt_plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture21/images/logo.png b/test/fixtures/fixture21/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture21/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture21/images/preview1.png b/test/fixtures/fixture21/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture21/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture21/ketch-manifest.yaml b/test/fixtures/fixture21/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture21/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture21/objects/legalBasis1.yaml b/test/fixtures/fixture21/objects/legalBasis1.yaml new file mode 100644 index 0000000..5aeefad --- /dev/null +++ b/test/fixtures/fixture21/objects/legalBasis1.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: LegalBasis +metadata: + code: disclosure + name: Disclosure +data: + requiresOptIn: true diff --git a/test/fixtures/fixture22/alt_assets/image.png b/test/fixtures/fixture22/alt_assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture22/alt_assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture22/alt_objects/legalBasis1.yaml b/test/fixtures/fixture22/alt_objects/legalBasis1.yaml new file mode 100644 index 0000000..5aeefad --- /dev/null +++ b/test/fixtures/fixture22/alt_objects/legalBasis1.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: LegalBasis +metadata: + code: disclosure + name: Disclosure +data: + requiresOptIn: true diff --git a/test/fixtures/fixture22/alt_plugin/plugin.js b/test/fixtures/fixture22/alt_plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture22/alt_plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture22/images/logo.png b/test/fixtures/fixture22/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture22/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture22/images/preview1.png b/test/fixtures/fixture22/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture22/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture22/ketch-manifest.yaml b/test/fixtures/fixture22/ketch-manifest.yaml new file mode 100644 index 0000000..6179310 --- /dev/null +++ b/test/fixtures/fixture22/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture23/alt_assets/image.png b/test/fixtures/fixture23/alt_assets/image.png new file mode 100644 index 0000000..773b222 --- /dev/null +++ b/test/fixtures/fixture23/alt_assets/image.png @@ -0,0 +1 @@ +image diff --git a/test/fixtures/fixture23/alt_objects/legalBasis1.yaml b/test/fixtures/fixture23/alt_objects/legalBasis1.yaml new file mode 100644 index 0000000..5aeefad --- /dev/null +++ b/test/fixtures/fixture23/alt_objects/legalBasis1.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: LegalBasis +metadata: + code: disclosure + name: Disclosure +data: + requiresOptIn: true diff --git a/test/fixtures/fixture23/alt_plugin/plugin.js b/test/fixtures/fixture23/alt_plugin/plugin.js new file mode 100644 index 0000000..9658cc6 --- /dev/null +++ b/test/fixtures/fixture23/alt_plugin/plugin.js @@ -0,0 +1 @@ +alert(1); diff --git a/test/fixtures/fixture23/images/logo.png b/test/fixtures/fixture23/images/logo.png new file mode 100644 index 0000000..98a0152 --- /dev/null +++ b/test/fixtures/fixture23/images/logo.png @@ -0,0 +1 @@ +logo diff --git a/test/fixtures/fixture23/images/preview1.png b/test/fixtures/fixture23/images/preview1.png new file mode 100644 index 0000000..d238f8c --- /dev/null +++ b/test/fixtures/fixture23/images/preview1.png @@ -0,0 +1 @@ +preview1 diff --git a/test/fixtures/fixture23/ketch-manifest.yaml b/test/fixtures/fixture23/ketch-manifest.yaml new file mode 100644 index 0000000..18c2033 --- /dev/null +++ b/test/fixtures/fixture23/ketch-manifest.yaml @@ -0,0 +1,114 @@ +apiversion: v1 +kind: App +metadata: + code: fixture + name: ${APP_NAME} + description: Fixture description +data: + assets: [] + autoupgrade: true + capabilities: + - permitPropagation + contacts: + - email: technical@example.com + name: Technical + type: technical + customobjects: [] + customersupporturl: https://support + depends: a, b, c + detaileddescription: detailed desc + docurl: https://docs + expireusertokens: true + form: + - data: null + default: "" + description: "" + editable: false + maxlength: 0 + minlength: 0 + multiple: false + name: "input" + pattern: "" + placeholder: "" + required: false + showonview: false + showvalueonedit: false + spellcheck: false + type: "string" + homepageurl: https://homepage + identityspaces: + - linked: + code: linked + description: linked identity + filters: + - format: raw + type: ios_advertising_id + name: linked idfa + managed: null + - linked: null + managed: + code: managed + description: managed identity + format: raw + name: managed aaid + type: android_advertising_id + variable: + jwt: + key: key + location: claims + location: cookie + name: myjwt + infourl: https://info + instances: single + logo: + code: logo + contenttype: image/png + contents: [] + height: 234 + link: images/logo.png + title: Logo + width: 345 + permissions: + - scope1 + previews: + - code: preview + contenttype: image/png + contents: [] + height: 123 + link: images/preview1.png + title: Preview 1 + width: 456 + primarycategory: privacy + privacypolicyurl: https://privacy + provides: + - sku1 + - sku2 + redirectonupdate: true + refreshinterval: 2h + requestuserauth: true + rules: + install: to install + view: to view + secondarycategory: privacy + setupurl: https://setup + shortdescription: short description + statusurl: https://status + supportedlanguages: + - en + supportedpurposes: + - analytics + supportedrights: + - delete + tosurl: https://tos + type: custom + userauthcallbackurl: https://auth + version: 0.0.0 + webhook: + authorization: "" + events: + - ping + maxqps: 0 + secret: [] + tls: + insecure: true + url: https://webhook diff --git a/test/fixtures/fixture3/ketch-manifest.yaml b/test/fixtures/fixture3/ketch-manifest.yaml new file mode 100644 index 0000000..2e2cfdb --- /dev/null +++ b/test/fixtures/fixture3/ketch-manifest.yaml @@ -0,0 +1,2 @@ +apiVersion: v1 +kind: App diff --git a/test/fixtures/fixture4/ketch-manifest.yaml b/test/fixtures/fixture4/ketch-manifest.yaml new file mode 100644 index 0000000..8e7a21b --- /dev/null +++ b/test/fixtures/fixture4/ketch-manifest.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: App +metadata: + diff --git a/test/fixtures/fixture5/ketch-manifest.yaml b/test/fixtures/fixture5/ketch-manifest.yaml new file mode 100644 index 0000000..510371b --- /dev/null +++ b/test/fixtures/fixture5/ketch-manifest.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: App +metadata: + code: fixture +data: + diff --git a/test/fixtures/fixture6/ketch-manifest.yaml b/test/fixtures/fixture6/ketch-manifest.yaml new file mode 100644 index 0000000..d34ec6c --- /dev/null +++ b/test/fixtures/fixture6/ketch-manifest.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: App +metadata: + code: fixture +data: + primaryCategory: privacy diff --git a/test/fixtures/fixture7/ketch-manifest.yaml b/test/fixtures/fixture7/ketch-manifest.yaml new file mode 100644 index 0000000..e824e0b --- /dev/null +++ b/test/fixtures/fixture7/ketch-manifest.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: App +metadata: + code: fixture + name: Fixture +data: + primaryCategory: privacy diff --git a/test/fixtures/fixture8/ketch-manifest.yaml b/test/fixtures/fixture8/ketch-manifest.yaml new file mode 100644 index 0000000..cc25571 --- /dev/null +++ b/test/fixtures/fixture8/ketch-manifest.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + primaryCategory: privacy diff --git a/test/fixtures/fixture9/ketch-manifest.yaml b/test/fixtures/fixture9/ketch-manifest.yaml new file mode 100644 index 0000000..2f23fc4 --- /dev/null +++ b/test/fixtures/fixture9/ketch-manifest.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: App +metadata: + code: fixture + name: Fixture + description: Fixture description +data: + primaryCategory: privacy + secondaryCategory: privacy diff --git a/test/ketch-manifest.yaml b/test/ketch-manifest.yaml deleted file mode 100644 index a1762d7..0000000 --- a/test/ketch-manifest.yaml +++ /dev/null @@ -1,107 +0,0 @@ -# ___________________________________________________________________________________________________________________________________________________________________________ -# Basic Details -name: Amplitude -version: 0.0.0 -primaryCategory: privacy -rules: - view: "test_access OR real_access" - install: "test_access AND some_access" -capabilities: - - rightPropagation -supportedLanguages: - - en -purposes: - - data_broking - - email_mktg - - personalization - - behavioral_advertising - - analytics -rights: - - delete - - portability -identitySpaces: - - code: device_id - name: Device ID - description: Amplitude defined device identifier. - managed: true - type: unique_browser - format: raw - variable: - location: cookie - name: "amplitude_id*" - jwt: - location: header - key: deviceId - - code: user_id - name: User ID - description: Amplitude identifier as specified by customer in the Amplitude setup process. Usually a pseudonymous account identifier. - managed: false - filters: - - type: email - format: raw - -# ___________________________________________________________________________________________________________________________________________________________________________ -# Branding -shortDescription: | - Manage all your website tags without editing code. Google Tag Manager delivers simple, reliable, easily integrated tag management solutions for free. -detailedDescription: | - Manage all your website tags without editing code. Google Tag Manager delivers simple, - reliable, easily integrated tag management solutions for free. -homepageURL: http://https://amplitude.com/ -customerSupportURL: https://help.amplitude.com/hc/en-us/requests/new -privacyPolicyURL: https://amplitude.com/privacy -statusURL: "https://ketch.com" -tosURL: https://support.google.com/tagmanager/answer/7157428?hl=en -docURL: https://docs.ketch.com/ -logo: - title: "Amplitude Logo" - link: "assets/amplitude.svg" -previews: - - title: "Amplitude Screenshot1" - link: "assets/screenshot1.png" - width: 123 - height: 456 - - title: "Amplitude Screenshot2" - link: "assets/screenshot2.png" - width: 123 - height: 456 -contacts: - - type: technical - email: dev@email.com - - type: marketing - email: marketing@email.com - - type: finance - email: billing@email.com - - type: security - email: security@email.com - -# ___________________________________________________________________________________________________________________________________________________________________________ -# Developer Information -expireUserTokens: false -requestUserAuth: false -redirectOnUpdate: false -refreshInterval: 5h -userAuthCallbackURL: "https://ketchapp.com/callback" -infoURL: "https://ketchapp.com/info" -setupURL: "https://ketchapp.com/setup" -webhook: - url: "https://ketch.com" - secret: "test123" - events: - - "rightInvocation.created" - authorization: "Bearer token" -permissionNote: "This app needs access to your marketplace" -permissions: - - "marketplace:read" - -# ___________________________________________________________________________________________________________________________________________________________________________ -# Setup Form -form: -- name: organizationID - title: "Organization ID" - type: string - required: true - minLength: 5 - maxLength: 100 - placeholder: Please input an Organization ID - spellcheck: false diff --git a/utils/yaml.go b/utils/yaml.go new file mode 100644 index 0000000..79d7c2d --- /dev/null +++ b/utils/yaml.go @@ -0,0 +1,19 @@ +package utils + +import ( + "encoding/json" + "gopkg.in/yaml.v3" +) + +func YAMLtoJSON(b []byte) ([]byte, error) { + if len(b) == 0 { + return nil, nil + } + + var in map[string]interface{} + if err := yaml.Unmarshal(b, &in); err != nil { + return nil, err + } + + return json.Marshal(in) +}