Passed
Push — master ( 7fc31c...e5d363 )
by Igor
04:51 queued 02:47
created

application.Version   A

Complexity

Conditions 2

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 0
cts 2
cp 0
crap 6
1
package application
2
3
import (
4
	"context"
5
	"fmt"
6
	"log"
7
8
	"github.com/muonsoft/openapi-mock/internal/application/config"
9
	"github.com/muonsoft/openapi-mock/internal/application/di"
10
	"github.com/spf13/cobra"
11
)
12
13
const descriptionTemplate = `OpenAPI Mock tool with random data generation.
14
Version %s. Build at %s.
15
16
See documentation at https://github.com/muonsoft/openapi-mock/blob/master/docs/usage_guide.md.`
17
18
type Options struct {
19
	SpecificationURL  string
20
	Version           string
21
	BuildTime         string
22
	ConfigFilename    string
23
	Arguments         []string
24
	DryRun            bool
25
	overrideArguments bool
26
}
27
28
type OptionFunc func(options *Options)
29
30
func Version(version string) OptionFunc {
31
	return func(options *Options) {
32
		options.Version = version
33
	}
34
}
35
36
func BuildTime(buildTime string) OptionFunc {
37
	return func(options *Options) {
38
		options.BuildTime = buildTime
39
	}
40
}
41
42
func Arguments(args []string) OptionFunc {
43 1
	return func(options *Options) {
44 1
		options.Arguments = args
45 1
		options.overrideArguments = true
46
	}
47
}
48
49
func Execute(options ...OptionFunc) error {
50 1
	opts := &Options{}
51 1
	for _, setOption := range options {
52 1
		setOption(opts)
53
	}
54
55 1
	mainCommand := newMainCommand(opts)
56 1
	if opts.overrideArguments {
57 1
		mainCommand.SetArgs(opts.Arguments)
58
	}
59
60 1
	return mainCommand.Execute()
61
}
62
63
func newMainCommand(opts *Options) *cobra.Command {
64 1
	mainCommand := &cobra.Command{
65
		Use:   "openapi-mock",
66
		Short: "OpenAPI Mock tool with random data generation",
67
		Long:  fmt.Sprintf(descriptionTemplate, opts.Version, opts.BuildTime),
68
	}
69
70 1
	mainCommand.PersistentFlags().StringVarP(
71
		&opts.ConfigFilename,
72
		"configuration",
73
		"c",
74
		"",
75
		`Configuration filename in JSON/YAML format. By default configuration is loaded from 'openapi-mock.yaml', 'openapi-mock.yml' or 'openapi-mock.json'.`,
76
	)
77 1
	mainCommand.PersistentFlags().StringVarP(
78
		&opts.SpecificationURL,
79
		"specification-url",
80
		"u",
81
		"",
82
		`URL or path to file with OpenAPI v3 specification. Overrides specification defined in configuration file or environment variable.`,
83
	)
84 1
	mainCommand.PersistentFlags().BoolVar(&opts.DryRun, "dry-run", false, `Dry run will not start a server`)
85
86 1
	mainCommand.AddCommand(
87
		newVersionCommand(opts),
88
		newServeCommand(opts),
89
		newValidateCommand(opts),
90
	)
91
92 1
	return mainCommand
93
}
94
95
func newVersionCommand(options *Options) *cobra.Command {
96 1
	return &cobra.Command{
97
		Use:   "version",
98
		Short: "Prints application version",
99
		Run: func(cmd *cobra.Command, args []string) {
100
			fmt.Printf("OpenAPI Mock tool. Version %s built at %s.\n", options.Version, options.BuildTime)
101
		},
102
	}
103
}
104
105
func newServeCommand(options *Options) *cobra.Command {
106 1
	return &cobra.Command{
107
		Use:           "serve",
108
		Short:         "Starts an HTTP server for generating mock responses by OpenAPI specification",
109
		SilenceUsage:  true,
110
		SilenceErrors: true,
111
		RunE: func(cmd *cobra.Command, args []string) error {
112 1
			configuration, err := config.Load(options.ConfigFilename)
113 1
			if err != nil {
114
				return err
115
			}
116 1
			configuration.DryRun = options.DryRun
117 1
			if options.SpecificationURL != "" {
118 1
				configuration.SpecificationURL = options.SpecificationURL
119
			}
120
121 1
			factory := di.NewFactory(configuration)
122 1
			server, err := factory.CreateHTTPServer()
123 1
			if err != nil {
124 1
				return err
125
			}
126
127 1
			if !options.DryRun {
128
				err = server.Run()
129
				if err != nil {
130
					return err
131
				}
132
			}
133
134 1
			return nil
135
		},
136
	}
137
}
138
139
func newValidateCommand(options *Options) *cobra.Command {
140 1
	return &cobra.Command{
141
		Use:           "validate",
142
		Short:         "Validates an OpenAPI specification",
143
		SilenceUsage:  true,
144
		SilenceErrors: true,
145
		RunE: func(cmd *cobra.Command, args []string) error {
146 1
			configuration, err := config.Load(options.ConfigFilename)
147 1
			if err != nil {
148
				return err
149
			}
150 1
			if options.SpecificationURL != "" {
151 1
				configuration.SpecificationURL = options.SpecificationURL
152
			}
153
154 1
			factory := di.NewFactory(configuration)
155 1
			loader := factory.CreateSpecificationLoader()
156 1
			specification, err := loader.LoadFromURI(configuration.SpecificationURL)
157 1
			if err != nil {
158
				return err
159
			}
160
161 1
			err = specification.Validate(context.Background())
162 1
			if err != nil {
163
				return fmt.Errorf(
164
					"validation of OpenAPI specification '%s' failed: %w",
165
					configuration.SpecificationURL,
166
					err,
167
				)
168
			}
169
170 1
			if !options.DryRun {
171
				log.Printf("OpenAPI specification '%s' is valid", configuration.SpecificationURL)
172
			}
173
174 1
			return nil
175
		},
176
	}
177
}
178