How to use repair method of vcs Package

Best Syzkaller code snippet using vcs.repair

env.go

Source:env.go Github

copy

Full Screen

1// Copyright (c) 2015-2022 CloudJ Technology Co., Ltd.2package apps3import (4 "cloudiac/common"5 "cloudiac/portal/consts"6 "cloudiac/portal/consts/e"7 "cloudiac/portal/libs/ctx"8 "cloudiac/portal/libs/db"9 "cloudiac/portal/libs/page"10 "cloudiac/portal/models"11 "cloudiac/portal/models/forms"12 "cloudiac/portal/models/resps"13 "cloudiac/portal/services"14 "cloudiac/portal/services/vcsrv"15 "cloudiac/utils/logs"16 "fmt"17 "net/http"18 "sort"19 "strings"20 "time"21 "github.com/robfig/cron/v3"22 "github.com/lib/pq"23)24// SpecParser 最小时间单位为分钟25// 每隔1 分钟执行一次 */1 * * * ?26// 每天 23点 执行一次 0 23 * * ?27// 每个月1号23 点执行一次 0 23 1 * ?28// 每天的0点、13点、18点、21点都执行一次:0 0,13,18,21 * * ?29var SpecParser = cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)30func ParseCronpress(cronDriftExpress string) (*time.Time, e.Error) {31 expr, err := SpecParser.Parse(cronDriftExpress)32 if err != nil {33 return nil, e.New(e.BadParam, http.StatusBadRequest, err)34 }35 // 根据当前时间算出下次该环境下次执行偏移检测任务时间36 nextTime := expr.Next(time.Now())37 return &nextTime, nil38}39// 获取环境偏移检测任务类型并且检查其参数40func GetCronTaskTypeAndCheckParam(cronExpress string, autoRepairDrift, openCronDrift bool) (string, e.Error) {41 if openCronDrift {42 if cronExpress == "" {43 return "", e.New(e.BadParam, http.StatusBadRequest, "Please set cronExpress when openCronDrift is set")44 }45 }46 if autoRepairDrift {47 if !openCronDrift || cronExpress == "" {48 return "", e.New(e.BadParam, http.StatusBadRequest, "Please set openCronDrift to true when autoRepairDrift is set")49 }50 }51 if openCronDrift {52 if !autoRepairDrift {53 return models.TaskTypePlan, nil54 } else {55 return models.TaskTypeApply, nil56 }57 }58 // 未开启漂移检测任务59 return "", nil60}61type CronDriftParam struct {62 CronDriftExpress *string `json:"cronDriftExpress"` // 偏移检测表达式63 AutoRepairDrift *bool `json:"autoRepairDrift"` // 是否进行自动纠偏64 OpenCronDrift *bool `json:"openCronDrift"` // 是否开启偏移检测65 NextDriftTaskTime *time.Time `json:"nextDriftTaskTime"` // 下次执行偏移检测任务的时间66}67func GetCronDriftParam(form forms.CronDriftForm) (*CronDriftParam, e.Error) {68 cronDriftParam := &CronDriftParam{}69 if form.HasKey("cronDriftExpress") || form.HasKey("autoRepairDrift") || form.HasKey("openCronDrift") {70 cronTaskType, err := GetCronTaskTypeAndCheckParam(form.CronDriftExpress, form.AutoRepairDrift, form.OpenCronDrift)71 if err != nil {72 return nil, err73 }74 if form.HasKey("autoRepairDrift") {75 cronDriftParam.AutoRepairDrift = &form.AutoRepairDrift76 }77 if form.HasKey("openCronDrift") {78 cronDriftParam.OpenCronDrift = &form.OpenCronDrift79 }80 if cronTaskType != "" {81 // 如果任务类型不为空,说明配置了漂移检测任务82 cronDriftParam.CronDriftExpress = &form.CronDriftExpress83 nextTime, err := ParseCronpress(form.CronDriftExpress)84 if err != nil {85 return nil, err86 }87 cronDriftParam.NextDriftTaskTime = nextTime88 } else {89 // 更新配置取消漂移检测任务,将下次重试时间重置为nil90 cronDriftParam.NextDriftTaskTime = nil91 }92 }93 return cronDriftParam, nil94}95func GetNextCronTime(cronExpress string) (*time.Time, e.Error) {96 if cronExpress == "" {97 return nil, e.New(e.BadParam, "cron express is empty")98 }99 return ParseCronpress(cronExpress)100}101func createEnvCheck(c *ctx.ServiceContext, form *forms.CreateEnvForm) e.Error {102 if c.OrgId == "" || c.ProjectId == "" {103 return e.New(e.BadRequest, http.StatusBadRequest)104 }105 // 检查自动纠漂移、推送到分支时重新部署时,是否了配置自动审批106 if !services.CheckoutAutoApproval(form.AutoApproval, form.AutoRepairDrift, form.Triggers) {107 return e.New(e.EnvCheckAutoApproval, http.StatusBadRequest)108 }109 if form.Playbook != "" && form.KeyId == "" {110 return e.New(e.TemplateKeyIdNotSet)111 }112 if er := services.CheckEnvTags(form.Tags); er != nil {113 return er114 }115 return nil116}117//nolint118func setDefaultValueFromTpl(form *forms.CreateEnvForm, tpl *models.Template, destroyAt, deployAt *models.Time, session *db.Session) e.Error {119 if !form.HasKey("tfVarsFile") {120 form.TfVarsFile = tpl.TfVarsFile121 }122 if !form.HasKey("playVarsFile") {123 form.PlayVarsFile = tpl.PlayVarsFile124 }125 if !form.HasKey("playbook") {126 form.Playbook = tpl.Playbook127 }128 if !form.HasKey("keyId") {129 form.KeyId = tpl.KeyId130 }131 if !form.HasKey("workdir") {132 form.Workdir = tpl.Workdir133 }134 if !form.HasKey("revision") {135 form.Revision = tpl.RepoRevision136 }137 if !form.HasKey("policyEnable") {138 form.PolicyEnable = tpl.PolicyEnable139 }140 if form.PolicyEnable {141 if !form.HasKey("policyGroup") || len(form.PolicyGroup) == 0 {142 temp, err := services.GetPolicyRels(session, tpl.Id, consts.ScopeTemplate)143 if err != nil {144 return err145 }146 policyGroups := make([]models.Id, 0)147 for _, v := range temp {148 policyGroups = append(policyGroups, models.Id(v.PolicyGroupId))149 }150 form.PolicyGroup = policyGroups151 }152 }153 if form.StepTimeout == 0 {154 form.StepTimeout = common.DefaultTaskStepTimeout155 }156 if form.DestroyAt != "" {157 var err error158 *destroyAt, err = models.Time{}.Parse(form.DestroyAt)159 if err != nil {160 return e.New(e.BadParam, http.StatusBadRequest, err)161 }162 } else if form.TTL != "" {163 _, err := services.ParseTTL(form.TTL) // 检查 ttl 格式164 if err != nil {165 return e.New(e.BadParam, http.StatusBadRequest, err)166 }167 } else if form.AutoDestroyCron != "" {168 // 活跃环境同步修改 destroyAt169 at, err := GetNextCronTime(form.AutoDestroyCron)170 if err != nil {171 return err172 }173 mt := models.Time(*at)174 destroyAt = &mt175 }176 if form.DeployAt != "" {177 var err error178 *deployAt, err = models.Time{}.Parse(form.DeployAt)179 if err != nil {180 return e.New(e.BadParam, http.StatusBadRequest, err)181 }182 } else if form.AutoDeployCron != "" {183 // 活跃环境同步修改 deployAt184 at, err := GetNextCronTime(form.AutoDeployCron)185 if err != nil {186 return err187 }188 mt := models.Time(*at)189 deployAt = &mt190 }191 return nil192}193// getTaskStepTimeoutInSecond return timeout in second194func getTaskStepTimeoutInSecond(timeoutInMinute int) (int, e.Error) {195 timeoutInSecond := timeoutInMinute * 60196 if timeoutInSecond <= 0 {197 sysTimeout, err := services.GetSystemTaskStepTimeout(db.Get())198 if err != nil {199 return -1, err200 }201 timeoutInSecond = sysTimeout202 }203 return timeoutInSecond, nil204}205func createEnvToDB(tx *db.Session, c *ctx.ServiceContext, form *forms.CreateEnvForm, envModel models.Env) (*models.Env, e.Error) {206 // 检查偏移检测参数207 cronTaskType, err := GetCronTaskTypeAndCheckParam(form.CronDriftExpress, form.AutoRepairDrift, form.OpenCronDrift)208 if err != nil {209 return nil, err210 }211 // 如果定时任务存在,保存参数到表内容212 if cronTaskType != "" {213 nextTime, err := ParseCronpress(form.CronDriftExpress)214 if err != nil {215 return nil, err216 }217 envModel.NextDriftTaskTime = nextTime218 }219 env, err := services.CreateEnv(tx, envModel)220 if err != nil && err.Code() == e.EnvAlreadyExists {221 _ = tx.Rollback()222 return nil, e.New(err.Code(), err, http.StatusBadRequest)223 } else if err != nil {224 _ = tx.Rollback()225 c.Logger().Errorf("error creating env, err %s", err)226 return nil, e.New(err.Code(), err, http.StatusInternalServerError)227 }228 return env, nil229}230func handlerCreateEnvVars(tx *db.Session, c *ctx.ServiceContext, form *forms.CreateEnvForm, env *models.Env) ([]string, []models.VariableBody, e.Error) {231 // sampleVariables是外部下发的环境变量,会和计算出来的变量列表冲突,这里需要做一下处理232 // FIXME 未对变量组的变量进行处理233 sampleVars, err := services.GetSampleValidVariables(tx, c.OrgId, c.ProjectId, env.TplId, env.Id, form.SampleVariables)234 if err != nil {235 return nil, nil, e.New(err.Code(), err, http.StatusInternalServerError)236 }237 if len(sampleVars) > 0 {238 form.Variables = append(form.Variables, sampleVars...)239 }240 // 创建变量241 updateVarsForm := forms.UpdateObjectVarsForm{242 Scope: consts.ScopeEnv,243 ObjectId: env.Id,244 Variables: form.Variables,245 }246 if _, er := updateObjectVars(c, tx, &updateVarsForm); er != nil {247 _ = tx.Rollback()248 return nil, nil, e.AutoNew(er, e.InternalError)249 }250 // 创建变量组与实例的关系251 if err := services.BatchUpdateRelationship(tx, form.VarGroupIds, form.DelVarGroupIds, consts.ScopeEnv, env.Id.String()); err != nil {252 _ = tx.Rollback()253 return nil, nil, err254 }255 targets := make([]string, 0)256 if len(strings.TrimSpace(form.Targets)) > 0 {257 targets = strings.Split(strings.TrimSpace(form.Targets), ",")258 }259 // 计算变量列表260 vars, er := services.GetValidVarsAndVgVars(tx, env.OrgId, env.ProjectId, env.TplId, env.Id)261 if er != nil {262 _ = tx.Rollback()263 return nil, nil, err264 }265 // 绑定策略组266 if len(form.PolicyGroup) > 0 {267 policyForm := &forms.UpdatePolicyRelForm{268 Id: env.Id,269 Scope: consts.ScopeEnv,270 PolicyGroupIds: form.PolicyGroup,271 }272 if _, err = services.UpdatePolicyRel(tx, policyForm); err != nil {273 _ = tx.Rollback()274 return nil, nil, err275 }276 }277 return targets, vars, nil278}279func getCreateEnvTpl(c *ctx.ServiceContext, form *forms.CreateEnvForm) (*models.Template, e.Error) {280 query := c.DB().Where("status = ?", models.Enable)281 tpl, err := services.GetTemplateById(query, form.TplId)282 if err != nil && err.Code() == e.TemplateNotExists {283 return nil, e.New(err.Code(), err, http.StatusBadRequest)284 } else if err != nil {285 c.Logger().Errorf("error get template, err %s", err)286 return nil, e.New(e.DBError, err, http.StatusInternalServerError)287 }288 return tpl, nil289}290func envWorkdirCheck(c *ctx.ServiceContext, repoId, repoRevision, workdir string, vcsId models.Id) e.Error {291 searchForm := &forms.RepoFileSearchForm{292 RepoId: repoId,293 RepoRevision: repoRevision,294 VcsId: vcsId,295 Workdir: workdir,296 }297 results, err := VcsRepoFileSearch(c, searchForm, "", consts.TfFileMatch)298 if err != nil {299 return err300 }301 if len(results) == 0 {302 return e.New(e.TemplateWorkdirError, fmt.Errorf("no '%s' files", consts.TfFileMatch))303 }304 return nil305}306// CreateEnv 创建环境307// nolint:cyclop308func CreateEnv(c *ctx.ServiceContext, form *forms.CreateEnvForm) (*models.EnvDetail, e.Error) {309 c.AddLogField("action", fmt.Sprintf("create env %s", form.Name))310 err := createEnvCheck(c, form)311 if err != nil {312 return nil, err313 }314 err = services.IsTplAssociationCurrentProject(c, form.TplId)315 if err != nil {316 return nil, err317 }318 // 检查模板319 tpl, err := getCreateEnvTpl(c, form)320 if err != nil {321 return nil, err322 }323 // 以下值只在未传入时使用模板定义的值,如果入参有该字段即使值为空也不会使用模板中的值324 var (325 destroyAt models.Time326 deployAt models.Time327 )328 err = setDefaultValueFromTpl(form, tpl, &destroyAt, &deployAt, c.DB())329 if err != nil {330 return nil, err331 }332 // 检查环境传入工作目录333 if err = envWorkdirCheck(c, tpl.RepoId, form.Revision, form.Workdir, tpl.VcsId); err != nil {334 return nil, err335 }336 tx := c.Tx()337 defer func() {338 if r := recover(); r != nil {339 _ = tx.Rollback()340 panic(r)341 }342 }()343 taskStepTimeout, err := getTaskStepTimeoutInSecond(form.StepTimeout)344 if err != nil {345 return nil, err346 }347 envModel := models.Env{348 OrgId: c.OrgId,349 ProjectId: c.ProjectId,350 CreatorId: c.UserId,351 TplId: form.TplId,352 Name: form.Name,353 Tags: strings.TrimSpace(form.Tags),354 RunnerId: form.RunnerId,355 RunnerTags: strings.Join(form.RunnerTags, ","),356 Status: models.EnvStatusInactive,357 OneTime: form.OneTime,358 StepTimeout: taskStepTimeout,359 // 模板参数360 TfVarsFile: form.TfVarsFile,361 PlayVarsFile: form.PlayVarsFile,362 Playbook: form.Playbook,363 Revision: form.Revision,364 KeyId: form.KeyId,365 Workdir: form.Workdir,366 TTL: form.TTL,367 AutoDestroyAt: &destroyAt,368 AutoApproval: form.AutoApproval,369 StopOnViolation: form.StopOnViolation,370 Triggers: form.Triggers,371 RetryAble: form.RetryAble,372 RetryDelay: form.RetryDelay,373 RetryNumber: form.RetryNumber,374 ExtraData: models.JSON(form.ExtraData),375 Callback: form.Callback,376 AutoRepairDrift: form.AutoRepairDrift,377 CronDriftExpress: form.CronDriftExpress,378 OpenCronDrift: form.OpenCronDrift,379 PolicyEnable: form.PolicyEnable,380 AutoDeployAt: &deployAt,381 AutoDeployCron: form.AutoDeployCron,382 AutoDestroyCron: form.AutoDestroyCron,383 }384 if tpl.IsDemo {385 // 演示环境强制设置自动销毁386 envModel.IsDemo = true387 envModel.TTL = consts.DemoEnvTTL388 envModel.AutoDestroyAt = nil389 envModel.AutoApproval = true390 }391 env, err := createEnvToDB(tx, c, form, envModel)392 if err != nil {393 return nil, err394 }395 targets, vars, err := handlerCreateEnvVars(tx, c, form, env)396 if err != nil {397 return nil, err398 }399 // 来源:手动触发、外部调用400 taskSource, taskSourceSys := getEnvSource(form.Source)401 // 创建任务402 task, err := services.CreateTask(tx, tpl, env, models.Task{403 Name: models.Task{}.GetTaskNameByType(form.TaskType),404 Targets: targets,405 CreatorId: c.UserId,406 KeyId: env.KeyId,407 Variables: vars,408 AutoApprove: env.AutoApproval,409 Revision: env.Revision,410 StopOnViolation: env.StopOnViolation,411 BaseTask: models.BaseTask{412 Type: form.TaskType,413 StepTimeout: taskStepTimeout,414 RunnerId: env.RunnerId,415 },416 ExtraData: models.JSON(form.ExtraData),417 Callback: form.Callback,418 Source: taskSource,419 SourceSys: taskSourceSys,420 })421 if err != nil {422 _ = tx.Rollback()423 c.Logger().Errorf("error creating task, err %s", err)424 return nil, e.New(err.Code(), err, http.StatusInternalServerError)425 }426 // 首次部署,直接更新 last_task_id427 env.LastTaskId = task.Id428 if _, err := tx.Save(env); err != nil {429 _ = tx.Rollback()430 c.Logger().Errorf("error save env, err %s", err)431 return nil, e.New(e.DBError, err, http.StatusInternalServerError)432 }433 // 创建完成434 if err := tx.Commit(); err != nil {435 _ = tx.Rollback()436 c.Logger().Errorf("error commit env, err %s", err)437 return nil, e.New(e.DBError, err)438 }439 envDetail := models.EnvDetail{440 Env: *env,441 TaskId: task.Id,442 Operator: c.Username,443 OperatorId: c.UserId,444 }445 vcs, _ := services.QueryVcsByVcsId(tpl.VcsId, c.DB())446 // 获取token447 token, err := GetWebhookToken(c)448 if err != nil {449 return nil, err450 }451 if err := vcsrv.SetWebhook(vcs, tpl.RepoId, token.Key, form.Triggers); err != nil {452 c.Logger().Errorf("set webhook err :%v", err)453 }454 // 记录操作日志455 services.InsertUserOperateLog(c.UserId, c.OrgId, env.Id, consts.OperatorObjectTypeEnv, "create", env.Name, nil)456 return &envDetail, nil457}458// SearchEnv 环境查询459func SearchEnv(c *ctx.ServiceContext, form *forms.SearchEnvForm) (interface{}, e.Error) {460 if c.OrgId == "" || c.ProjectId == "" {461 return nil, e.New(e.BadRequest, http.StatusBadRequest)462 }463 //query := c.DB().Where("iac_env.org_id = ? AND iac_env.project_id = ?", c.OrgId, c.ProjectId)464 query := services.QueryEnvDetail(c.DB(), c.OrgId, c.ProjectId)465 var er e.Error466 // 环境状态过滤467 query, er = services.FilterEnvStatus(query, form.Status, form.Deploying)468 if er != nil {469 return nil, er470 }471 // 环境归档状态过滤472 query, er = services.FilterEnvArchiveStatus(query, form.Archived)473 if er != nil {474 return nil, er475 }476 // 环境更新时间过滤477 query = services.FilterEnvUpdatedTime(query, form.StartTime, form.EndTime)478 if form.Q != "" {479 qs := "%" + form.Q + "%"480 query = query.Joins("left join iac_template on iac_env.tpl_id = iac_template.id")481 query = query.Where("iac_env.name LIKE ? OR iac_template.name LIKE ? OR iac_env.tags LIKE ?", qs, qs, qs)482 }483 // 默认按创建时间逆序排序484 if form.SortField() == "" {485 query = query.Order("iac_env.created_at DESC")486 } else {487 query = form.Order(query)488 }489 p := page.New(form.CurrentPage(), form.PageSize(), query)490 details := make([]*models.EnvDetail, 0)491 if err := p.Scan(&details); err != nil {492 return nil, e.New(e.DBError, err)493 }494 enabledBill, err := services.ProjectEnabledBill(c.DB(), c.ProjectId)495 if err != nil {496 return nil, e.AutoNew(err, e.DBError)497 }498 for _, env := range details {499 env.MergeTaskStatus()500 PopulateLastTask(c.DB(), env)501 env.PolicyStatus = models.PolicyStatusConversion(env.PolicyStatus, env.PolicyEnable)502 // runner tags 数组形式返回503 if env.Env.RunnerTags != "" {504 env.RunnerTags = strings.Split(env.Env.RunnerTags, ",")505 } else {506 env.RunnerTags = []string{}507 }508 // 以分钟为单位返回509 env.StepTimeout = env.StepTimeout / 60510 // 是否开启费用采集511 env.IsBilling = enabledBill512 }513 return page.PageResp{514 Total: p.MustTotal(),515 PageSize: p.Size,516 List: details,517 }, nil518}519// PopulateLastTask 导出 last task 相关数据520func PopulateLastTask(query *db.Session, env *models.EnvDetail) *models.EnvDetail {521 if env.LastTaskId != "" {522 if lastTask, _ := services.GetTaskById(query, env.LastTaskId); lastTask != nil {523 // 密钥524 if env.KeyId != lastTask.KeyId {525 if key, _ := services.GetKeyById(query, lastTask.KeyId, false); key != nil {526 env.KeyId = lastTask.KeyId527 env.KeyName = key.Name528 }529 }530 // 返回环境详情时会调用该函数,且返回的数据会用于创建新的部署任务时在表单中回显,531 // 而对于 vcs webhook 自动触发的任务其 revision 可能与环境的不同,这就会导致重新部署环境时使用的不是环境当前配置的分支。532 // 为了避免这种情况,这里我们不将环境的 Revision 设置为最后一次任务的 revision533 // env.Revision = lastTask.Revision // 分支/标签534 // 部署通道535 env.RunnerId = lastTask.RunnerId536 // Commit id537 env.CommitId = lastTask.CommitId538 // 执行人539 if operator, _ := services.GetUserByIdRaw(query, lastTask.CreatorId); operator != nil {540 env.Operator = operator.Name541 env.OperatorId = lastTask.CreatorId542 }543 }544 }545 return env546}547func checkUserHasApprovalPerm(c *ctx.ServiceContext) error {548 if c.IsSuperAdmin ||549 services.UserHasOrgRole(c.UserId, c.OrgId, consts.OrgRoleAdmin) ||550 services.UserHasProjectRole(c.UserId, c.OrgId, c.ProjectId, consts.ProjectRoleManager) ||551 services.UserHasProjectRole(c.UserId, c.OrgId, c.ProjectId, consts.ProjectRoleApprover) {552 return nil553 }554 return e.New(e.PermDenyApproval, http.StatusForbidden)555}556func updateEnvCheck(orgId, projectId models.Id, form *forms.UpdateEnvForm) e.Error {557 if orgId == "" || projectId == "" {558 return e.New(e.BadRequest, http.StatusBadRequest)559 }560 // 检查自动纠漂移、推送到分支时重新部署时,是否了配置自动审批561 if !services.CheckoutAutoApproval(form.AutoApproval, form.AutoRepairDrift, form.Triggers) {562 return e.New(e.EnvCheckAutoApproval, http.StatusBadRequest)563 }564 return nil565}566func getEnvForUpdate(tx *db.Session, c *ctx.ServiceContext, form *forms.UpdateEnvForm) (*models.Env, e.Error) {567 query := tx.Where("iac_env.org_id = ? AND iac_env.project_id = ?", c.OrgId, c.ProjectId)568 env, err := services.GetEnvById(query, form.Id)569 if err != nil && err.Code() != e.EnvNotExists {570 _ = tx.Rollback()571 return nil, e.New(err.Code(), err, http.StatusNotFound)572 } else if err != nil {573 _ = tx.Rollback()574 c.Logger().Errorf("error get env, err %s", err)575 return nil, e.New(e.DBError, err, http.StatusInternalServerError)576 }577 // 项目已归档,不允许编辑578 if env.Archived && !form.Archived {579 return nil, e.New(e.EnvArchived, http.StatusBadRequest)580 }581 return env, nil582}583func setUpdateEnvByForm(attrs models.Attrs, form *forms.UpdateEnvForm) {584 if form.HasKey("name") {585 attrs["name"] = form.Name586 }587 if form.HasKey("description") {588 attrs["description"] = form.Description589 }590 if form.HasKey("keyId") {591 attrs["key_id"] = form.KeyId592 }593 if form.HasKey("runnerId") {594 attrs["runner_id"] = form.RunnerId595 }596 if form.HasKey("retryAble") {597 attrs["retryAble"] = form.RetryAble598 }599 if form.HasKey("retryNumber") {600 attrs["retryNumber"] = form.RetryNumber601 }602 if form.HasKey("retryDelay") {603 attrs["retryDelay"] = form.RetryDelay604 }605 if form.HasKey("stopOnViolation") {606 attrs["StopOnViolation"] = form.StopOnViolation607 }608 if form.HasKey("policyEnable") {609 attrs["policyEnable"] = form.PolicyEnable610 }611 if form.HasKey("stepTimeout") {612 // 将分钟转换为秒613 attrs["stepTimeout"] = form.StepTimeout * 60614 }615}616func setAndCheckUpdateEnvAutoApproval(c *ctx.ServiceContext, tx *db.Session, attrs models.Attrs, env *models.Env, form *forms.UpdateEnvForm) e.Error {617 if form.HasKey("autoApproval") {618 if form.AutoApproval != env.AutoApproval {619 if err := checkUserHasApprovalPerm(c); err != nil {620 _ = tx.Rollback()621 return e.AutoNew(err, e.PermissionDeny)622 }623 }624 attrs["auto_approval"] = form.AutoApproval625 }626 return nil627}628func setAndCheckUpdateEnvDeploy(tx *db.Session, attrs models.Attrs, env *models.Env, form *forms.UpdateEnvForm) e.Error {629 if !form.HasKey("deployAt") && !form.HasKey("autoDeployCron") {630 return nil631 }632 if form.HasKey("deployAt") {633 deployAt, err := models.Time{}.Parse(form.DeployAt)634 if err != nil {635 _ = tx.Rollback()636 return e.New(e.BadParam, http.StatusBadRequest, err)637 }638 attrs["auto_deploy_at"] = &deployAt639 attrs["auto_deploy_cron"] = ""640 }641 if form.HasKey("autoDeployCron") {642 attrs["auto_deploy_at"] = nil643 attrs["auto_deploy_cron"] = form.AutoDeployCron644 if form.AutoDeployCron != "" {645 // 活跃环境同步修改 deployAt646 at, err := GetNextCronTime(form.AutoDeployCron)647 if err != nil {648 return err649 }650 mt := models.Time(*at)651 attrs["auto_deploy_at"] = &mt652 }653 }654 return nil655}656func setAndCheckUpdateEnvDestroy(tx *db.Session, attrs models.Attrs, env *models.Env, form *forms.UpdateEnvForm) e.Error {657 if !form.HasKey("destroyAt") && !form.HasKey("ttl") && !form.HasKey("autoDestroyCron") {658 return nil659 }660 if form.HasKey("destroyAt") {661 destroyAt, err := models.Time{}.Parse(form.DestroyAt)662 if err != nil {663 _ = tx.Rollback()664 return e.New(e.BadParam, http.StatusBadRequest, err)665 }666 attrs["auto_destroy_at"] = &destroyAt667 attrs["ttl"] = "" // 直接传入了销毁时间,需要同步清空 ttl668 attrs["auto_destroy_cron"] = ""669 } else if form.HasKey("ttl") {670 ttl, err := services.ParseTTL(form.TTL)671 if err != nil {672 _ = tx.Rollback()673 return e.New(e.BadParam, http.StatusBadRequest, err)674 }675 attrs["ttl"] = form.TTL676 if ttl == 0 {677 // ttl 传 0 表示重置销毁时间678 attrs["auto_destroy_at"] = nil679 } else if env.Status != models.EnvStatusDestroyed && env.Status != models.EnvStatusInactive {680 // 活跃环境同步修改 destroyAt681 at := models.Time(time.Now().Add(ttl))682 attrs["auto_destroy_at"] = &at683 }684 attrs["auto_destroy_cron"] = ""685 }686 if form.HasKey("autoDestroyCron") {687 attrs["ttl"] = ""688 attrs["auto_destroy_at"] = nil689 attrs["auto_destroy_cron"] = form.AutoDestroyCron690 if form.AutoDestroyCron != "" {691 // 活跃环境同步修改 destroyAt692 at, err := GetNextCronTime(form.AutoDestroyCron)693 if err != nil {694 return err695 }696 mt := models.Time(*at)697 attrs["auto_destroy_at"] = &mt698 }699 }700 return nil701}702func setAndCheckUpdateEnvTriggers(c *ctx.ServiceContext, tx *db.Session, attrs models.Attrs, env *models.Env, form *forms.UpdateEnvForm) e.Error {703 if form.HasKey("triggers") {704 attrs["triggers"] = pq.StringArray(form.Triggers)705 // triggers有变更时,需要检测webhook的配置706 tpl, err := services.GetTemplateById(c.DB(), env.TplId)707 if err != nil && err.Code() == e.TemplateNotExists {708 _ = tx.Rollback()709 return e.New(err.Code(), err, http.StatusBadRequest)710 } else if err != nil {711 c.Logger().Errorf("error get template, err %s", err)712 _ = tx.Rollback()713 return e.New(e.DBError, err, http.StatusInternalServerError)714 }715 vcs, _ := services.QueryVcsByVcsId(tpl.VcsId, c.DB())716 // 获取token717 token, err := GetWebhookToken(c)718 if err != nil {719 _ = tx.Rollback()720 return err721 }722 if err := vcsrv.SetWebhook(vcs, tpl.RepoId, token.Key, form.Triggers); err != nil {723 c.Logger().Errorf("set webhook err :%v", err)724 }725 }726 return nil727}728func setAndCheckUpdateEnvByForm(c *ctx.ServiceContext, tx *db.Session, attrs models.Attrs, env *models.Env, form *forms.UpdateEnvForm) e.Error {729 if form.HasKey("tags") {730 if er := services.CheckEnvTags(form.Tags); er != nil {731 return er732 } else {733 attrs["tags"] = strings.TrimSpace(form.Tags)734 }735 }736 if !env.IsDemo { // 演示环境不允许修改自动审批和存活时间737 if err := setAndCheckUpdateEnvAutoApproval(c, tx, attrs, env, form); err != nil {738 return err739 }740 if err := setAndCheckUpdateEnvDestroy(tx, attrs, env, form); err != nil {741 return err742 }743 if err := setAndCheckUpdateEnvDeploy(tx, attrs, env, form); err != nil {744 return err745 }746 }747 if err := setAndCheckUpdateEnvTriggers(c, tx, attrs, env, form); err != nil {748 return err749 }750 if form.HasKey("archived") {751 if env.Status != models.EnvStatusInactive && env.Status != models.EnvStatusDestroyed {752 _ = tx.Rollback()753 return e.New(e.EnvCannotArchiveActive,754 fmt.Errorf("env can't be archive while env is %s", env.Status),755 http.StatusBadRequest)756 }757 attrs["archived"] = form.Archived758 if form.Name != "" {759 attrs["name"] = form.Name760 }761 }762 return nil763}764// UpdateEnv 环境编辑765func UpdateEnv(c *ctx.ServiceContext, form *forms.UpdateEnvForm) (*models.EnvDetail, e.Error) { // nolint:cyclop766 c.AddLogField("action", fmt.Sprintf("update env %s", form.Id))767 if err := updateEnvCheck(c.OrgId, c.ProjectId, form); err != nil {768 return nil, err769 }770 tx := c.Tx()771 defer func() {772 if r := recover(); r != nil {773 _ = tx.Rollback()774 panic(r)775 }776 }()777 env, err := getEnvForUpdate(tx, c, form)778 if err != nil {779 _ = tx.Rollback()780 return nil, err781 }782 if env.Locked {783 _ = tx.Rollback()784 return nil, e.New(e.EnvLocked, http.StatusBadRequest)785 }786 if !env.Archived {787 if form.Archived {788 // 环境归档时自动重新命名789 form.Name = env.Name + "-archived-" + time.Now().Format("20060102150405")790 }791 }792 attrs := models.Attrs{}793 cronDriftParam, err := GetCronDriftParam(forms.CronDriftForm{794 BaseForm: form.BaseForm,795 CronDriftExpress: form.CronDriftExpress,796 AutoRepairDrift: form.AutoRepairDrift,797 OpenCronDrift: form.OpenCronDrift,798 })799 if err != nil {800 _ = tx.Rollback()801 return nil, err802 }803 // 先更新合规绑定,若失败则不进行后续更新操作804 if form.HasKey("policyGroup") && len(form.PolicyGroup) > 0 {805 policyForm := &forms.UpdatePolicyRelForm{806 Id: env.Id,807 Scope: consts.ScopeEnv,808 PolicyGroupIds: form.PolicyGroup,809 }810 if _, err = services.UpdatePolicyRel(tx, policyForm); err != nil {811 _ = tx.Rollback()812 return nil, err813 }814 }815 attrs["autoRepairDrift"] = cronDriftParam.AutoRepairDrift816 attrs["openCronDrift"] = cronDriftParam.OpenCronDrift817 attrs["cronDriftExpress"] = cronDriftParam.CronDriftExpress818 attrs["nextDriftTaskTime"] = cronDriftParam.NextDriftTaskTime819 setUpdateEnvByForm(attrs, form)820 err = setAndCheckUpdateEnvByForm(c, tx, attrs, env, form)821 if err != nil {822 return nil, err823 }824 env, err = services.UpdateEnv(tx, form.Id, attrs)825 if err != nil && err.Code() == e.EnvAliasDuplicate {826 _ = tx.Rollback()827 return nil, e.New(err.Code(), err, http.StatusBadRequest)828 } else if err != nil {829 _ = tx.Rollback()830 c.Logger().Errorf("error update env, err %s", err)831 return nil, err832 }833 env.MergeTaskStatus()834 detail := &models.EnvDetail{Env: *env}835 detail = PopulateLastTask(tx, detail)836 if err := tx.Commit(); err != nil {837 _ = tx.Rollback()838 return nil, e.New(e.DBError, err)839 }840 // 记录操作日志841 services.InsertUserOperateLog(c.UserId, c.OrgId, env.Id, consts.OperatorObjectTypeEnv, "update", form.Name, nil)842 return detail, nil843}844// EnvDetail 环境信息详情845func EnvDetail(c *ctx.ServiceContext, form forms.DetailEnvForm) (*models.EnvDetail, e.Error) {846 if c.OrgId == "" || c.ProjectId == "" {847 return nil, e.New(e.BadRequest, http.StatusBadRequest)848 }849 //query := c.DB().Where("iac_env.org_id = ? AND iac_env.project_id = ?", c.OrgId, c.ProjectId)850 query := services.QueryEnvDetail(c.DB(), c.OrgId, c.ProjectId)851 envDetail, err := services.GetEnvDetailById(query, form.Id)852 if err != nil && err.Code() == e.EnvNotExists {853 return nil, e.New(e.EnvNotExists, err, http.StatusNotFound)854 } else if err != nil {855 c.Logger().Errorf("error get env by id, err %s", err)856 return nil, e.New(e.DBError, err)857 }858 enabledBill, err := services.ProjectEnabledBill(c.DB(), envDetail.ProjectId)859 if err != nil {860 return nil, e.AutoNew(err, e.DBError)861 }862 envDetail.MergeTaskStatus()863 envDetail = PopulateLastTask(c.DB(), envDetail)864 resp, err := services.GetPolicyRels(c.DB(), form.Id, consts.ScopeEnv)865 if err != nil {866 return nil, err867 }868 envDetail.PolicyGroup = make([]string, 0)869 for _, v := range resp {870 envDetail.PolicyGroup = append(envDetail.PolicyGroup, v.PolicyGroupId)871 }872 envDetail.PolicyStatus = models.PolicyStatusConversion(envDetail.PolicyStatus, envDetail.PolicyEnable)873 // 时间转化为分钟874 envDetail.StepTimeout = envDetail.StepTimeout / 60875 // runner tags 数组形式返回876 if envDetail.Env.RunnerTags != "" {877 envDetail.RunnerTags = strings.Split(envDetail.Env.RunnerTags, ",")878 } else {879 envDetail.RunnerTags = []string{}880 }881 // 是否开启费用采集882 envDetail.IsBilling = enabledBill883 return envDetail, nil884}885// EnvDeploy 创建新部署任务886// 任务类型:plan, apply, destroy887func EnvDeploy(c *ctx.ServiceContext, form *forms.DeployEnvForm) (ret *models.EnvDetail, er e.Error) {888 _ = c.DB().Transaction(func(tx *db.Session) error {889 ret, er = envDeploy(c, tx, form)890 return er891 })892 // 记录操作日志893 services.InsertUserOperateLog(c.UserId, c.OrgId, form.Id, consts.OperatorObjectTypeEnv, form.TaskType, form.Name, nil)894 return ret, er895}896// EnvDeployCheck 创建新部署前检测897func EnvDeployCheck(c *ctx.ServiceContext, envId models.Id) (interface{}, e.Error) {898 if c.OrgId == "" || c.ProjectId == "" {899 return nil, e.New(e.BadRequest, http.StatusBadRequest)900 }901 env, err := services.GetEnvById(c.DB(), envId)902 if err != nil {903 return nil, err904 }905 //判断环境是否已归档906 if env.Archived {907 return nil, e.New(e.EnvArchived, "Environment archived")908 }909 // 云模板检测910 tpl, err := services.GetTplByEnvId(c.DB(), envId)911 if err != nil {912 return nil, err913 }914 //检测云模板是否绑定项目915 _, checkErr := services.GetBindTemplate(c.DB(), c.ProjectId, tpl.Id)916 if checkErr != nil {917 return nil, checkErr918 }919 //vcs 检测(是否禁用,token是否有效)920 vcs, err := services.GetVcsById(c.DB(), tpl.VcsId)921 if err != nil {922 return nil, err923 }924 if vcs.Status != "enable" {925 return nil, e.New(e.VcsError, "vcs is disable")926 }927 if err := services.VscTokenCheckByID(c.DB(), vcs.Id, vcs.VcsToken); err != nil {928 return nil, e.New(e.VcsInvalidToken, err)929 }930 //环境运行中不允许再手动发布任务931 tasks, err := services.GetActiveTaskByEnvId(c.DB(), envId)932 if err != nil {933 return nil, err934 }935 if len(tasks) > 0 {936 return nil, e.New(e.EnvDeploying, "Deployment initiation is not allowed")937 }938 return nil, nil939}940func envPreCheck(orgId, projectId, keyId models.Id, playbook string) e.Error {941 if orgId == "" || projectId == "" {942 return e.New(e.BadRequest, http.StatusBadRequest)943 }944 if playbook != "" && keyId == "" {945 return e.New(e.TemplateKeyIdNotSet)946 }947 return nil948}949func envCheck(tx *db.Session, orgId, projectId, id models.Id, lg logs.Logger) (*models.Env, e.Error) {950 envQuery := services.QueryWithProjectId(services.QueryWithOrgId(tx, orgId), projectId)951 env, err := services.GetEnvById(envQuery, id)952 if err != nil && err.Code() != e.EnvNotExists {953 return nil, e.New(err.Code(), err, http.StatusNotFound)954 } else if err != nil {955 lg.Errorf("error get env, err %s", err)956 return nil, e.New(e.DBError, err, http.StatusInternalServerError)957 }958 // env 状态检查959 if env.Archived {960 return nil, e.New(e.EnvArchived, http.StatusBadRequest)961 }962 if env.Deploying {963 return nil, e.New(e.EnvDeploying, http.StatusBadRequest)964 }965 return env, nil966}967func envTplCheck(tx *db.Session, orgId, tplId models.Id, lg logs.Logger) (*models.Template, e.Error) {968 tplQuery := services.QueryWithOrgId(tx, orgId)969 tpl, err := services.GetTemplateById(tplQuery, tplId)970 if err != nil && err.Code() == e.TemplateNotExists {971 return nil, e.New(err.Code(), err, http.StatusBadRequest)972 } else if err != nil {973 lg.Errorf("error get template, err %s", err)974 return nil, e.New(e.DBError, err, http.StatusInternalServerError)975 }976 if tpl.Status == models.Disable {977 return nil, e.New(e.TemplateDisabled, http.StatusBadRequest)978 }979 return tpl, nil980}981func setEnvByForm(env *models.Env, form *forms.DeployEnvForm) {982 if form.HasKey("name") {983 env.Name = form.Name984 }985 if form.HasKey("stopOnViolation") {986 env.StopOnViolation = form.StopOnViolation987 }988 if form.HasKey("triggers") {989 env.Triggers = form.Triggers990 }991 if form.HasKey("keyId") {992 env.KeyId = form.KeyId993 }994 if form.HasKey("stepTimeout") {995 // 将分钟转换为秒996 env.StepTimeout = form.StepTimeout * 60997 }998 if form.HasKey("tfVarsFile") {999 env.TfVarsFile = form.TfVarsFile1000 }1001 if form.HasKey("playVarsFile") {1002 env.PlayVarsFile = form.PlayVarsFile1003 }1004 if form.HasKey("playbook") {1005 env.Playbook = form.Playbook1006 }1007 if form.HasKey("revision") {1008 env.Revision = form.Revision1009 }1010 if form.HasKey("retryAble") {1011 env.RetryAble = form.RetryAble1012 }1013 if form.HasKey("retryNumber") {1014 env.RetryNumber = form.RetryNumber1015 }1016 if form.HasKey("retryDelay") {1017 env.RetryDelay = form.RetryDelay1018 }1019 if form.HasKey("policyEnable") {1020 env.PolicyEnable = form.PolicyEnable1021 }1022 if form.HasKey("workdir") {1023 env.Workdir = form.Workdir1024 }1025 setEnvRunnerInfoByForm(env, form)1026}1027func setEnvRunnerInfoByForm(env *models.Env, form *forms.DeployEnvForm) {1028 if form.HasKey("runnerId") {1029 env.RunnerId = form.RunnerId1030 }1031 if form.HasKey("runnerTags") {1032 env.RunnerTags = strings.Join(form.RunnerTags, ",")1033 // 如果传了 tags 则清空 runnerId 值1034 env.RunnerId = ""1035 }1036}1037func setAndCheckEnvAutoApproval(c *ctx.ServiceContext, env *models.Env, form *forms.DeployEnvForm) e.Error {1038 if form.HasKey("autoApproval") {1039 if form.AutoApproval != env.AutoApproval {1040 if err := checkUserHasApprovalPerm(c); err != nil {1041 return e.AutoNew(err, e.PermissionDeny)1042 }1043 }1044 env.AutoApproval = form.AutoApproval1045 }1046 return nil1047}1048func setAndCheckEnvAutoDeploy(tx *db.Session, env *models.Env, form *forms.DeployEnvForm) e.Error { //nolint:dupl1049 if !form.HasKey("deployAt") && !form.HasKey("autoDeployCron") {1050 return nil1051 }1052 if form.HasKey("deployAt") {1053 deployAt, err := models.Time{}.Parse(form.DeployAt)1054 if err != nil {1055 return e.New(e.BadParam, http.StatusBadRequest, err)1056 }1057 env.AutoDeployAt = &deployAt1058 // 直接传入了部署时间,需要同步清空 ttl1059 env.AutoDeployCron = ""1060 }1061 if form.HasKey("autoDeployCron") {1062 env.AutoDeployAt = nil1063 env.AutoDeployCron = form.AutoDeployCron1064 if env.AutoDeployCron != "" {1065 // 非活跃环境同步修改 deployAt1066 at, err := GetNextCronTime(env.AutoDeployCron)1067 if err != nil {1068 return err1069 }1070 mt := models.Time(*at)1071 env.AutoDeployAt = &mt1072 }1073 }1074 return nil1075}1076func setAndCheckEnvAutoDestroy(tx *db.Session, env *models.Env, form *forms.DeployEnvForm) e.Error { //nolint:dupl1077 if !form.HasKey("destroyAt") && !form.HasKey("ttl") && !form.HasKey("autoDestroyCron") {1078 return nil1079 }1080 if form.HasKey("destroyAt") {1081 destroyAt, err := models.Time{}.Parse(form.DestroyAt)1082 if err != nil {1083 return e.New(e.BadParam, http.StatusBadRequest, err)1084 }1085 env.AutoDestroyAt = &destroyAt1086 // 直接传入了销毁时间,需要同步清空 ttl1087 env.TTL = ""1088 env.AutoDestroyCron = ""1089 } else if form.HasKey("ttl") {1090 ttl, err := services.ParseTTL(form.TTL)1091 if err != nil {1092 return e.New(e.BadParam, http.StatusBadRequest, err)1093 }1094 env.TTL = form.TTL1095 if ttl == 0 { // ttl 传入 0 表示清空自动销毁时间1096 env.AutoDestroyAt = nil1097 } else if env.Status != models.EnvStatusDestroyed && env.Status != models.EnvStatusInactive {1098 // 活跃环境同步修改 destroyAt1099 at := models.Time(time.Now().Add(ttl))1100 env.AutoDestroyAt = &at1101 }1102 env.AutoDestroyCron = ""1103 }1104 if form.HasKey("autoDestroyCron") {1105 env.TTL = ""1106 env.AutoDestroyAt = nil1107 env.AutoDestroyCron = form.AutoDestroyCron1108 if env.AutoDestroyCron != "" {1109 // 活跃环境同步修改 destroyAt1110 at, err := GetNextCronTime(env.AutoDestroyCron)1111 if err != nil {1112 return err1113 }1114 mt := models.Time(*at)1115 env.AutoDestroyAt = &mt1116 }1117 }1118 return nil1119}1120func setAndCheckEnvDriftCron(env *models.Env, form *forms.DeployEnvForm) e.Error {1121 cronDriftParam, err := GetCronDriftParam(forms.CronDriftForm{1122 BaseForm: form.BaseForm,1123 CronDriftExpress: form.CronDriftExpress,1124 AutoRepairDrift: form.AutoRepairDrift,1125 OpenCronDrift: form.OpenCronDrift,1126 })1127 if err != nil {1128 return err1129 }1130 if cronDriftParam.AutoRepairDrift != nil {1131 env.AutoRepairDrift = *cronDriftParam.AutoRepairDrift1132 }1133 if cronDriftParam.OpenCronDrift != nil {1134 env.OpenCronDrift = *cronDriftParam.OpenCronDrift1135 env.NextDriftTaskTime = cronDriftParam.NextDriftTaskTime1136 }1137 if cronDriftParam.CronDriftExpress != nil {1138 env.CronDriftExpress = *cronDriftParam.CronDriftExpress1139 }1140 return nil1141}1142func setAndCheckEnvByForm(c *ctx.ServiceContext, tx *db.Session, env *models.Env, form *forms.DeployEnvForm) e.Error {1143 if !env.IsDemo { // 演示环境不允许修改自动审批和自动销毁设置1144 if err := setAndCheckEnvAutoApproval(c, env, form); err != nil {1145 return err1146 }1147 if err := setAndCheckEnvAutoDestroy(tx, env, form); err != nil {1148 return err1149 }1150 if err := setAndCheckEnvAutoDeploy(tx, env, form); err != nil {1151 return err1152 }1153 }1154 // drift Cron 相关1155 if err := setAndCheckEnvDriftCron(env, form); err != nil {1156 return err1157 }1158 if form.HasKey("extraData") {1159 env.ExtraData = form.ExtraData1160 }1161 if form.HasKey("variables") {1162 updateVarsForm := forms.UpdateObjectVarsForm{1163 Scope: consts.ScopeEnv,1164 ObjectId: env.Id,1165 Variables: checkDeployVar(form.Variables),1166 }1167 if _, er := updateObjectVars(c, tx, &updateVarsForm); er != nil {1168 return e.AutoNew(er, e.InternalError)1169 }1170 }1171 if len(form.PolicyGroup) > 0 {1172 policyForm := &forms.UpdatePolicyRelForm{1173 Id: env.Id,1174 Scope: consts.ScopeEnv,1175 PolicyGroupIds: form.PolicyGroup,1176 }1177 if _, err := services.UpdatePolicyRel(tx, policyForm); err != nil {1178 _ = tx.Rollback()1179 return err1180 }1181 }1182 if form.TaskType == "" {1183 return e.New(e.BadParam, http.StatusBadRequest)1184 }1185 if form.HasKey("varGroupIds") || form.HasKey("delVarGroupIds") {1186 // 创建变量组与实例的关系1187 if err := services.BatchUpdateRelationship(tx, form.VarGroupIds, form.DelVarGroupIds, consts.ScopeEnv, env.Id.String()); err != nil {1188 return err1189 }1190 }1191 return nil1192}1193func envDeploy(c *ctx.ServiceContext, tx *db.Session, form *forms.DeployEnvForm) (*models.EnvDetail, e.Error) { // nolint:cyclop1194 c.AddLogField("action", fmt.Sprintf("deploy env task %s", form.Id))1195 lg := c.Logger()1196 if err := envPreCheck(c.OrgId, c.ProjectId, form.KeyId, form.Playbook); err != nil {1197 return nil, err1198 }1199 lg.Debugln("envDeploy -> envPreCheck finish")1200 // 检查自动纠漂移、推送到分支时重新部署时,是否了配置自动审批1201 if !services.CheckoutAutoApproval(form.AutoApproval, form.AutoRepairDrift, form.Triggers) {1202 return nil, e.New(e.EnvCheckAutoApproval, http.StatusBadRequest)1203 }1204 lg.Debugln("envDeploy -> CheckoutAutoApproval finish")1205 // env 检查1206 env, err := envCheck(tx, c.OrgId, c.ProjectId, form.Id, c.Logger())1207 if err != nil {1208 return nil, err1209 }1210 lg.Debugln("envDeploy -> envCheck finish")1211 if form.TaskType != common.TaskTypePlan && env.Locked {1212 return nil, e.New(e.EnvLocked, http.StatusBadRequest)1213 }1214 // 模板检查1215 tpl, err := envTplCheck(tx, c.OrgId, env.TplId, c.Logger())1216 if err != nil {1217 return nil, err1218 }1219 if !form.HasKey("workdir") {1220 form.Workdir = env.Workdir1221 }1222 if !form.HasKey("revision") {1223 form.Revision = env.Revision1224 }1225 // 环境下云模版工作目录检查1226 if err = envWorkdirCheck(c, tpl.RepoId, form.Revision, form.Workdir, tpl.VcsId); err != nil {1227 return nil, err1228 }1229 lg.Debugln("envDeploy -> envTplCheck finish")1230 // set env from form1231 setEnvByForm(env, form)1232 // set and check autoApproval, destroyAt, cronDrift, TaskType, variables...1233 err = setAndCheckEnvByForm(c, tx, env, form)1234 if err != nil {1235 return nil, err1236 }1237 lg.Debugln("envDeploy -> setAndCheckEnvByForm finish")1238 if env.IsDemo && env.Status == models.EnvStatusDestroyed {1239 // 演示环境销毁后重新部署也强制设置自动销毁1240 env.TTL = consts.DemoEnvTTL1241 env.AutoDestroyAt = nil1242 env.AutoApproval = true1243 }1244 targets := make([]string, 0)1245 if len(strings.TrimSpace(form.Targets)) > 0 {1246 targets = strings.Split(strings.TrimSpace(form.Targets), ",")1247 }1248 // 计算变量列表1249 vars, er := services.GetValidVarsAndVgVars(tx, env.OrgId, env.ProjectId, env.TplId, env.Id)1250 if er != nil {1251 return nil, err1252 }1253 lg.Debugln("envDeploy -> GetValidVarsAndVgVars finish")1254 // 获取实际执行任务的runnerID1255 rId, err := services.GetAvailableRunnerIdByStr(env.RunnerId, env.RunnerTags)1256 if err != nil {1257 return nil, err1258 }1259 // 来源:手动触发、外部调用1260 taskSource, taskSourceSys := getEnvSource(form.Source)1261 // 创建任务1262 task, err := services.CreateTask(tx, tpl, env, models.Task{1263 Name: models.Task{}.GetTaskNameByType(form.TaskType),1264 Targets: targets,1265 CreatorId: c.UserId,1266 KeyId: env.KeyId,1267 Variables: vars,1268 AutoApprove: env.AutoApproval,1269 Revision: env.Revision,1270 StopOnViolation: env.StopOnViolation,1271 ExtraData: env.ExtraData,1272 BaseTask: models.BaseTask{1273 Type: form.TaskType,1274 StepTimeout: env.StepTimeout,1275 RunnerId: rId,1276 },1277 Source: taskSource,1278 SourceSys: taskSourceSys,1279 })1280 if err != nil {1281 c.Logger().Errorf("error creating task, err %s", err)1282 return nil, e.New(err.Code(), err, http.StatusInternalServerError)1283 }1284 lg.Debugln("envDeploy -> CreateTask finish")1285 // Save() 调用会全量将结构体中的字段进行保存,即使字段为 zero value1286 if _, err := tx.Save(env); err != nil {1287 c.Logger().Errorf("error save env, err %s", err)1288 return nil, e.New(e.DBError, err, http.StatusInternalServerError)1289 }1290 env.MergeTaskStatus()1291 envDetail := &models.EnvDetail{1292 Env: *env,1293 TaskId: task.Id,1294 }1295 envDetail = PopulateLastTask(c.DB(), envDetail)1296 vcs, _ := services.QueryVcsByVcsId(tpl.VcsId, c.DB())1297 // 获取token1298 token, err := GetWebhookToken(c)1299 if err != nil {1300 return nil, err1301 }1302 if err := vcsrv.SetWebhook(vcs, tpl.RepoId, token.Key, form.Triggers); err != nil {1303 c.Logger().Errorf("set webhook err :%v", err)1304 }1305 return envDetail, nil1306}1307// SearchEnvResources 查询环境资源列表1308func SearchEnvResources(c *ctx.ServiceContext, form *forms.SearchEnvResourceForm) (interface{}, e.Error) {1309 if c.OrgId == "" || c.ProjectId == "" || form.Id == "" {1310 return nil, e.New(e.BadRequest, http.StatusBadRequest)1311 }1312 env, err := services.GetEnvById(c.DB(), form.Id)1313 if err != nil && err.Code() != e.EnvNotExists {1314 return nil, e.New(err.Code(), err, http.StatusNotFound)1315 } else if err != nil {1316 c.Logger().Errorf("error get env, err %s", err)1317 return nil, e.New(e.DBError, err, http.StatusInternalServerError)1318 }1319 // 无资源变更1320 if env.LastResTaskId == "" {1321 return getEmptyListResult(form)1322 }1323 return SearchTaskResources(c, &forms.SearchTaskResourceForm{1324 NoPageSizeForm: form.NoPageSizeForm,1325 Id: env.LastResTaskId,1326 Q: form.Q,1327 })1328}1329// EnvOutput 环境的 Terraform output1330// output 与 resource 返回源保持一致1331func EnvOutput(c *ctx.ServiceContext, form forms.DetailEnvForm) (interface{}, e.Error) {1332 if c.OrgId == "" || c.ProjectId == "" || form.Id == "" {1333 return nil, e.New(e.BadRequest, http.StatusBadRequest)1334 }1335 env, err := services.GetEnvById(c.DB(), form.Id)1336 if err != nil && err.Code() != e.EnvNotExists {1337 return nil, e.New(err.Code(), err, http.StatusNotFound)1338 } else if err != nil {1339 c.Logger().Errorf("error get env, err %s", err)1340 return nil, e.New(e.DBError, err, http.StatusInternalServerError)1341 }1342 // 无资源变更1343 if env.LastResTaskId == "" {1344 return nil, nil1345 }1346 return TaskOutput(c, forms.DetailTaskForm{1347 BaseForm: form.BaseForm,1348 Id: env.LastResTaskId,1349 })1350}1351// EnvVariables 获取环境的变量列表,环境部署对应的环境变量为 last task 固化的变量内容1352func EnvVariables(c *ctx.ServiceContext, form forms.SearchEnvVariableForm) (interface{}, e.Error) {1353 if c.OrgId == "" || c.ProjectId == "" || form.Id == "" {1354 return nil, e.New(e.BadRequest, http.StatusBadRequest)1355 }1356 task := models.Task{}1357 err := services.QueryWithOrgProject(c.DB(), c.OrgId, c.ProjectId, models.Task{}.TableName()).1358 Where("env_id = ? AND `type` IN (?)", form.Id,1359 []string{common.TaskTypePlan, common.TaskTypeApply, common.TaskTypeDestroy}).Last(&task)1360 if err != nil {1361 if e.IsRecordNotFound(err) {1362 return nil, e.New(e.ObjectNotExists, http.StatusNotFound)1363 }1364 c.Logger().Errorf("query env last task error: %v", err)1365 return nil, e.AutoNew(err, e.DBError)1366 }1367 // 隐藏敏感字段1368 for index, v := range task.Variables {1369 if v.Sensitive {1370 task.Variables[index].Value = ""1371 }1372 }1373 sort.Sort(task.Variables)1374 return task.Variables, nil1375}1376// ResourceDetail 查询部署成功后资源的详细信息1377func ResourceDetail(c *ctx.ServiceContext, form *forms.ResourceDetailForm) (*models.ResAttrs, e.Error) {1378 if c.OrgId == "" || c.ProjectId == "" || form.Id == "" {1379 return nil, e.New(e.BadRequest, http.StatusBadRequest)1380 }1381 resource, err := services.GetResourceById(c.DB(), form.ResourceId)1382 if err != nil {1383 c.Logger().Errorf("error get resource, err %s", err)1384 return nil, e.New(e.DBError, err, http.StatusInternalServerError)1385 }1386 if resource.EnvId != form.Id || resource.OrgId != c.OrgId || resource.ProjectId != c.ProjectId {1387 c.Logger().Errorf("Environment ID and resource ID do not match")1388 return nil, e.New(e.DBError, err, http.StatusForbidden)1389 }1390 resultAttrs := resource.Attrs1391 if len(resource.SensitiveKeys) > 0 {1392 set := map[string]interface{}{}1393 for _, value := range resource.SensitiveKeys {1394 set[value] = nil1395 }1396 for k := range resultAttrs {1397 // 如果state 中value 存在与sensitive 设置,展示时不展示详情1398 if _, ok := set[k]; ok {1399 resultAttrs[k] = "(sensitive value)"1400 }1401 }1402 }1403 return &resultAttrs, nil1404}1405// SearchEnvResourcesGraph 查询环境资源列表1406func SearchEnvResourcesGraph(c *ctx.ServiceContext, form *forms.SearchEnvResourceGraphForm) (interface{}, e.Error) {1407 if c.OrgId == "" || c.ProjectId == "" || form.Id == "" {1408 return nil, e.New(e.BadRequest, http.StatusBadRequest)1409 }1410 env, err := services.GetEnvById(c.DB(), form.Id)1411 if err != nil && err.Code() != e.EnvNotExists {1412 return nil, e.New(err.Code(), err, http.StatusNotFound)1413 } else if err != nil {1414 c.Logger().Errorf("error get env, err %s", err)1415 return nil, e.New(e.DBError, err, http.StatusInternalServerError)1416 }1417 // 无资源变更1418 if env.LastResTaskId == "" {1419 return nil, nil1420 }1421 return SearchTaskResourcesGraph(c, &forms.SearchTaskResourceGraphForm{1422 Id: env.LastResTaskId,1423 Dimension: form.Dimension,1424 })1425}1426// ResourceGraphDetail 查询部署成功后资源的详细信息1427func ResourceGraphDetail(c *ctx.ServiceContext, form *forms.ResourceGraphDetailForm) (interface{}, e.Error) {1428 if c.OrgId == "" || c.ProjectId == "" || form.Id == "" {1429 return nil, e.New(e.BadRequest, http.StatusBadRequest)1430 }1431 resource, err := services.GetResourceById(c.DB(), form.ResourceId)1432 if err != nil {1433 c.Logger().Errorf("error get resource, err %s", err)1434 return nil, e.New(e.DBError, err, http.StatusInternalServerError)1435 }1436 res, err := services.GetResourceDetail(c.DB(), c.OrgId, c.ProjectId, form.Id, resource.Id)1437 if err != nil {1438 c.Logger().Errorf("error get resource, err %s", err)1439 return nil, e.New(e.DBError, err, http.StatusInternalServerError)1440 }1441 if res.EnvId != form.Id || res.OrgId != c.OrgId || res.ProjectId != c.ProjectId {1442 c.Logger().Errorf("Environment ID and resource ID do not match")1443 return nil, e.New(e.DBError, err, http.StatusForbidden)1444 }1445 resultAttrs := resource.Attrs1446 if len(res.SensitiveKeys) > 0 {1447 set := map[string]interface{}{}1448 for _, value := range resource.SensitiveKeys {1449 set[value] = nil1450 }1451 for k := range resultAttrs {1452 // 如果state 中value 存在与sensitive 设置,展示时不展示详情1453 if _, ok := set[k]; ok {1454 resultAttrs[k] = "(sensitive value)"1455 }1456 }1457 }1458 if res.DriftDetail != "" {1459 res.IsDrift = true1460 }1461 res.Attrs = resultAttrs1462 return res, nil1463}1464func EnvUpdateTags(c *ctx.ServiceContext, form *forms.UpdateEnvTagsForm) (resp interface{}, er e.Error) {1465 if er := services.CheckEnvTags(form.Tags); er != nil {1466 return nil, er1467 }1468 query := services.QueryWithOrgProject(c.DB(), c.OrgId, c.ProjectId)1469 tags := strings.TrimSpace(form.Tags)1470 if env, er := services.UpdateEnv(query, form.Id, models.Attrs{"tags": tags}); er != nil {1471 return nil, er1472 } else {1473 return env, nil1474 }1475}1476func EnvLock(c *ctx.ServiceContext, form *forms.EnvLockForm) (interface{}, e.Error) {1477 tx := c.Tx()1478 defer func() {1479 if r := recover(); r != nil {1480 _ = tx.Rollback()1481 }1482 }()1483 // 查询环境下是否有执行中、待审批、排队中的任务1484 tasks, err := services.GetActiveTaskByEnvId(tx, form.Id)1485 if err != nil {1486 _ = tx.Rollback()1487 return nil, err1488 }1489 if len(tasks) > 0 {1490 _ = tx.Rollback()1491 return nil, e.New(e.EnvLockFailedTaskActive)1492 }1493 env, err := services.GetEnvDetailById(tx, form.Id)1494 if err != nil {1495 _ = tx.Rollback()1496 return nil, err1497 }1498 if env.IsDemo {1499 _ = tx.Rollback()1500 return nil, e.New(e.EnvLockedFailedEnvIsDemo)1501 }1502 if err := services.EnvLock(tx, form.Id); err != nil {1503 _ = tx.Rollback()1504 return nil, err1505 }1506 if err := tx.Commit(); err != nil {1507 _ = tx.Rollback()1508 return nil, e.New(e.DBError, err)1509 }1510 return nil, nil1511}1512func EnvUnLock(c *ctx.ServiceContext, form *forms.EnvUnLockForm) (interface{}, e.Error) {1513 attrs := models.Attrs{}1514 attrs["locked"] = false1515 if form.ClearDestroyAt {1516 attrs["auto_destroy_at"] = nil1517 attrs["ttl"] = ""1518 }1519 if _, err := services.UpdateEnv(c.DB(), form.Id, attrs); err != nil {1520 return nil, err1521 }1522 return nil, nil1523}1524func EnvUnLockConfirm(c *ctx.ServiceContext, form *forms.EnvUnLockConfirmForm) (interface{}, e.Error) {1525 env, err := services.GetEnvById(c.DB(), form.Id)1526 if err != nil {1527 return nil, err1528 }1529 resp := resps.EnvUnLockConfirmResp{}1530 if env.AutoDestroyAt != nil && time.Now().Unix() > env.AutoDestroyAt.Unix() && env.AutoDestroyAt.Unix() > 0 {1531 resp.AutoDestroyPass = true1532 }1533 return resp, nil1534}1535// EnvStat 环境概览页统计数据1536func EnvStat(c *ctx.ServiceContext, form *forms.EnvParam) (interface{}, e.Error) {1537 tx := c.DB()1538 // 费用类型统计1539 envCostTypeStat, err := services.EnvCostTypeStat(tx, form.Id)1540 if err != nil {1541 return nil, err1542 }1543 // 费用趋势统计1544 envCostTrendStat, err := services.EnvCostTrendStat(tx, form.Id, 6)1545 if err != nil {1546 return nil, err1547 }1548 // 费用列表1549 envCostList, err := services.EnvCostList(tx, form.Id)1550 if err != nil {1551 return nil, err1552 }1553 var results = make([]resps.EnvCostDetailResp, 0)1554 for _, envCost := range envCostList {1555 results = append(results, resps.EnvCostDetailResp{1556 ResType: envCost.ResType,1557 ResAttr: GetResShowName(envCost.Attrs, envCost.Address),1558 InstanceId: envCost.InstanceId,1559 CurMonthCost: envCost.CurMonthCost,1560 TotalCost: envCost.TotalCost,1561 })1562 }1563 return &resps.EnvStatisticsResp{1564 CostTypeStat: envCostTypeStat,1565 CostTrendStat: envCostTrendStat,1566 CostList: results,1567 }, nil1568}1569func checkDeployVar(vars []forms.Variable) []forms.Variable {1570 resp := make([]forms.Variable, 0)1571 for _, v := range vars {1572 if v.Scope != consts.ScopeEnv {1573 continue1574 }1575 resp = append(resp, v)1576 }1577 return resp1578}1579func getEnvSource(source string) (taskSource string, taskSourceSys string) {1580 taskSource = consts.TaskSourceManual1581 taskSourceSys = ""1582 if source != consts.TaskSourceManual {1583 taskSource = consts.TaskSourceApi1584 taskSourceSys = source1585 }1586 return1587}...

Full Screen

Full Screen

viewResolver.go

Source:viewResolver.go Github

copy

Full Screen

...233 if err := recreateView(ctx, repoProvider, vw, restoreWs, r.logger, r.snapshotter); err != nil {234 return err235 }236 return nil237 }).ExecView(ws.CodebaseID, vw.ID, "repairView")238 if err != nil {239 return nil, gqlerrors.Error(err)240 }241 return r.resolveView(ctx, args.ID)242}243func (r *ViewRootResolver) CreateView(ctx context.Context, args resolvers.CreateViewArgs) (resolvers.ViewResolver, error) {244 userID, err := auth.UserID(ctx)245 if err != nil {246 return nil, gqlerrors.Error(err)247 }248 ws, err := r.workspaceReader.Get(string(args.Input.WorkspaceID))249 if err != nil {250 return nil, gqlerrors.Error(err)251 }252 if err := r.authService.CanWrite(ctx, ws); err != nil {253 return nil, gqlerrors.Error(err)254 }255 var mountPath *string256 if args.Input.MountPath != "" {257 mountPath = &args.Input.MountPath258 }259 var mountHostname *string260 if args.Input.MountHostname != "" {261 mountHostname = &args.Input.MountHostname262 }263 if v, err := r.viewService.Create(ctx, userID, ws, mountPath, mountHostname); errors.Is(err, service_view.ErrRebasing) {264 return nil, gqlerrors.Error(gqlerrors.ErrBadRequest, "message", "View is currently in rebasing state. Please resolve all the conflicts and try again.")265 } else if err != nil {266 return nil, gqlerrors.Error(err)267 } else {268 return &Resolver{v: v, root: r}, nil269 }270}271func recreateView(ctx context.Context, repoProvider provider.RepoProvider, vw *views.View, ws *workspaces.Workspace, logger *zap.Logger, gitSnapshotter *service_snapshots.Service) error {272 trunkPath := repoProvider.TrunkPath(vw.CodebaseID)273 newView := vw.ID + "-recreate-" + uuid.NewString()274 newViewPath := repoProvider.ViewPath(vw.CodebaseID, newView)275 backupPath := repoProvider.ViewPath(vw.CodebaseID, vw.ID+"-replaced-"+uuid.NewString())276 decoratedLogger := logger.Named("recreateView").With(zap.String("new_view_path", newViewPath), zap.String("backup_path", backupPath))277 decoratedLogger.Info("recreating view")278 if _, err := vcs.CloneRepo(trunkPath, newViewPath); err != nil {279 return err280 }281 if ws != nil {282 if err := view_vcs.SetWorkspace(repoProvider, vw.CodebaseID, newView, ws.ID); err != nil {283 return err284 }285 // Attempt to make a snapshot of the existing view286 snapshot, err := gitSnapshotter.Snapshot(ctx, vw.CodebaseID, vw.WorkspaceID, snapshots.ActionPreCheckoutOtherView, service_snapshots.WithOnView(vw.ID))287 if err != nil {288 return err289 }290 // TODO: What if we can't make a snapshot because the view is FUBAR?291 repo, err := repoProvider.ViewRepo(ws.CodebaseID, newView)292 if err != nil {293 return err294 }295 if err := vcs2.RestoreRepo(logger, repo, snapshot.ID, snapshot.CommitSHA); err != nil {296 return fmt.Errorf("failed to restore snapshot: %w", err)297 }298 decoratedLogger.Info("restored from snapshot", zap.Stringer("codebase_id", snapshot.CodebaseID), zap.String("commit_id", snapshot.CommitSHA))299 }300 // Swap replacement301 if err := os.Rename(repoProvider.ViewPath(vw.CodebaseID, vw.ID), backupPath); err != nil {302 return err303 }304 if err := os.Rename(newViewPath, repoProvider.ViewPath(vw.CodebaseID, vw.ID)); err != nil {305 return err306 }307 decoratedLogger.Info("repair view completed")308 return nil309}310type Resolver struct {311 v *views.View312 root *ViewRootResolver313}314func (r *Resolver) ID() graphql.ID {315 return graphql.ID(r.v.ID)316}317func (r *Resolver) MountPath() string {318 if r.v.MountPath == nil {319 return ""320 }321 return *r.v.MountPath...

Full Screen

Full Screen

activity_gift_monthly.go

Source:activity_gift_monthly.go Github

copy

Full Screen

...33 if has_gift && data != nil {34 if req.ReplenishSign {35 // 补签扣钱36 costItem := &gamedata.CostData{}37 repairSignCost := gamedata.GetCommonCfg().GetRepairSignCost()38 costItem.AddItem(gamedata.VI_Hc, repairSignCost) // 读配置39 ok := account.CostBySync(p.Account, costItem, resp, "MonthlyGift")40 if !ok {41 return rpcWarn(resp, errCode.ClickTooQuickly)42 }43 }44 setOk := player_gift.SetHasGet(player_vip, p.Profile.GetProfileNowTime(), req.ReplenishSign)45 if setOk != 0 {46 return rpcWarn(resp, setOk)47 }48 for _, dataIt := range data {49 ok := account.GiveBySyncWithoutMerge(p.Account, dataIt, resp, "MonthlyGift")50 if !ok {51 return rpcError(resp, CODE_Give_Err)52 }...

Full Screen

Full Screen

repair

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 vcs := contract.NewVcs()4 err := vcs.Repair()5 if err != nil {6 fmt.Println("Error: ", err)7 }8}9import (10func main() {11 vcs := contract.NewVcs()12 err := vcs.Repair()13 if err != nil {14 fmt.Println("Error: ", err)15 }16}17import (18func main() {19 vcs := contract.NewVcs()20 err := vcs.Repair()21 if err != nil {22 fmt.Println("Error: ", err)23 }24}25import (26func main() {27 vcs := contract.NewVcs()28 err := vcs.Repair()29 if err != nil {30 fmt.Println("Error: ", err)31 }32}33import (34func main() {35 vcs := contract.NewVcs()36 err := vcs.Repair()37 if err != nil {38 fmt.Println("Error: ", err)39 }40}41import (42func main() {43 vcs := contract.NewVcs()44 err := vcs.Repair()45 if err != nil {46 fmt.Println("Error: ", err)47 }48}49import (

Full Screen

Full Screen

repair

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 if len(os.Args) > 1 {4 } else {5 }6 vcs := vcs.NewVCS(path)7 vcs.Repair()8 fmt.Println(vcs.Status())9 fmt.Println(vcs.Log())10 fmt.Println(vcs.Diff())11 fmt.Println(vcs.Diff("HEAD~1", "HEAD"))12 fmt.Println(vcs.Diff("HEAD", "HEAD~1"))13 fmt.Println(vcs.Diff("HEAD~1", "HEAD~2"))14 fmt.Println(vcs.Diff("HEAD~2", "HEAD~1"))15 fmt.Println(vcs.Diff("HEAD~2", "HEAD~3"))16 fmt.Println(vcs.Diff("HEAD~3", "HEAD~2"))17 fmt.Println(vcs.Diff("HEAD~3", "HEAD~4"))18 fmt.Println(vcs.Diff("HEAD~4", "HEAD~3"))19 fmt.Println(vcs.Diff("HEAD~4", "HEAD~5"))20 fmt.Println(vcs.Diff("HEAD~5", "HEAD~4"))21 fmt.Println(vcs.Diff("HEAD~5", "HEAD~6"))22 fmt.Println(vcs.Diff("HEAD~6", "HEAD~5"))23 fmt.Println(vcs.Diff("HEAD~6", "HEAD~7"))24 fmt.Println(vcs.Diff("HEAD~7", "HEAD~6"))25 fmt.Println(vcs.Diff("HEAD~7", "HEAD~8"))

Full Screen

Full Screen

repair

Using AI Code Generation

copy

Full Screen

1import java.io.*;2public class 2 {3 public static void main(String[] args) throws IOException {4 String path = "C:\\Users\\Kushal\\Desktop\\vcs.txt";5 vcs v = new vcs();6 v.repair(path);7 }8}9import java.io.*;10public class 3 {11 public static void main(String[] args) throws IOException {12 String path = "C:\\Users\\Kushal\\Desktop\\vcs.txt";13 vcs v = new vcs();14 v.commit(path);15 }16}17import java.io.*;18public class 4 {19 public static void main(String[] args) throws IOException {20 String path = "C:\\Users\\Kushal\\Desktop\\vcs.txt";21 vcs v = new vcs();22 v.checkout(path);23 }24}25import java.io.*;26public class 5 {27 public static void main(String[] args) throws IOException {28 String path = "C:\\Users\\Kushal\\Desktop\\vcs.txt";29 vcs v = new vcs();30 v.status(path);31 }32}33import java.io.*;34public class 6 {35 public static void main(String[] args) throws IOException {36 String path = "C:\\Users\\Kushal\\Desktop\\vcs.txt";37 vcs v = new vcs();38 v.branch(path);39 }40}41import java.io.*;42public class 7 {43 public static void main(String[] args) throws IOException {44 String path = "C:\\Users\\Kushal\\Desktop\\vcs.txt";45 vcs v = new vcs();46 v.merge(path);47 }48}49import java.io.*;50public class 8 {51 public static void main(String[] args) throws IOException {52 String path = "C:\\Users\\Kushal\\Desktop\\vcs.txt";

Full Screen

Full Screen

repair

Using AI Code Generation

copy

Full Screen

1import ( 2func main() {3 VCS = vcs.VCS{Path: "/home/abhi18av/abhi18av/vcs"}4 VCS.Repair()5}6import ( 7func main() {8 VCS = vcs.VCS{Path: "/home/abhi18av/abhi18av/vcs"}9 VCS.Add("test.txt")10}11import ( 12func main() {13 VCS = vcs.VCS{Path: "/home/abhi18av/abhi18av/vcs"}14 VCS.Remove("test.txt")15}16import ( 17func main() {18 VCS = vcs.VCS{Path: "/home/abhi18av/abhi18av/vcs"}19 VCS.Commit("Added test.txt")20}21import ( 22func main() {23 VCS = vcs.VCS{Path: "/home/abhi18av/abhi18av/vcs"}24 VCS.Log()25}26import ( 27func main() {28 VCS = vcs.VCS{Path: "/home/abhi18av/abhi

Full Screen

Full Screen

repair

Using AI Code Generation

copy

Full Screen

1import java.util.*;2import java.io.*;3import java.text.SimpleDateFormat;4import java.util.Date;5public class 2 {6 public static void main(String[] args) throws Exception {7 vcs vcs = new vcs();8 vcs.repair();9 System.out.println(vcs);10 }11}12import java.util.*;13import java.io.*;14import java.text.SimpleDateFormat;15import java.util.Date;16public class vcs {17 private String name;18 private String version;19 private String date;20 private String description;21 private String author;22 private String author_email;23 private String maintainer;24 private String maintainer_email;25 private String license;26 private String url;27 private String download_url;28 private String keywords;29 private String classifiers;30 public vcs() {31 this.name = "vcs";32 this.version = "1.0";33 this.date = "2017-10-05";34 this.description = "version control system";35 this.author = "vcs";

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful