پس از استخدام در پارک علم و فناوری پردیس، یکی از غولهای تکنولوژی کشور در یک حرکت خلاقانه و در راستای خودکفایی تصمیم گرفته یک پیادهسازی فان از Docker
با نام Dockerious
توسعه دهد. این پروژه به عنوان پروژه شما در دوران آزمایشی تعیین شده. در فاز اول شرکتکنندگان باید بخش هستهای و ابتدایی این ابزار را پیادهسازی کنند.
شما باید یک ابزار خط فرمان (CLI) ساده بسازید که بتواند دستورات سیستمعامل را (البته از لیست مجاز قرار داده شده در internal/commands/allowed.go
) در پسزمینه اجرا کرده و وضعیت آنها را ترک کند.
جزئیات پروژه
پروژه اولیه را از این لینک دانلود کنید. ساختار پروژه به شکل زیر است:
├── cmd
│ ├── ps.go # TODO Implement
│ ├── root.go # TODO Implement
│ └── run.go # TODO Implement
├── go.mod
├── go.sum
├── internal
│ ├── commands
│ │ └── allowed.go
│ ├── db
│ │ └── database.go
│ ├── models
│ │ └── process.go
│ ├── monitor
│ │ └── monitor.go
│ └── types
│ └── status.go
├── main.go
در این پروژه، شما صرفا باید قسمتهای مشخص شده با // TODO
را در دایرکتوری cmd
پیادهسازی کنید. هدف اصلی، پیادهسازی منطق دو دستور اصلی dockerious run
و dockerious ps
است.
-
internal/commands/allowed.go
: یکmap
حاوی لیست دستورات مجاز (echo
,ls
,sleep
,pwd
) را تعریف میکند. -
internal/db/database.go
: مسئولیت اتصال به پایگاهداده PostgreSQL را بر عهده دارد. -
internal/models/process.go
: مدل GORM برای جدولprocesses
را تعریف میکند. -
internal/types/status.go
: وضعیتهای مختلف یک پروسه (running
,finished
,failed
) را به صورت ثابت تعریف میکند. -
internal/monitor/monitor.go
: یک اینترفیس برای نظارت بر چرخه حیات پروسهها تعریف میکند. شما باید پیادهسازی آن را درcmd/run.go
انجام دهید.
⚠️ نباید ساختار فایلهای داخل
internal
را تغییر دهید — فقطcmd/*.go
قسمتهایی که// TODO
دارند باید تکمیل شوند.
مدل پایگاهداده
ساختار جدول processes
در پایگاهداده که مدل آن در models/process.go
تعریف شده، به شرح زیر است:
فیلد | تایپ | توضیحات |
---|---|---|
ID |
uint |
کلید اصلی AUTO_INCREMENT |
PID |
int |
شناسهی پروسه که سیستمعامل برمیگرداند |
Command |
string |
دستور کامل اجرا شده |
Status |
string |
وضعیت پروسه (running ، finished ، failed ) |
CreatedAt |
time.Time |
زمان ایجاد رکورد |
UpdatedAt |
time.Time |
زمان آخرین بهروزرسانی رکورد |
DeletedAt |
time.Time |
زمان حذف رکورد |
دستورات خط فرمان
شما باید توابع و متدهای خالی مشخصشده با // TODO
را در فایلهای cmd/root.go
، cmd/run.go
و cmd/ps.go
کامل کنید.
فایل cmd/root.go
cmd/root.go
توضیح: این فایل مسئول راهاندازی ساختار اصلی CLI است. شما باید دستورات فرزند را به دستور ریشه متصل کرده و نقطهی ورود برنامه را تکمیل کنید.
نیازمندیها:
-
func init()
: در این تابع، باید دستوراتrunCmd
وpsCmd
را به عنوان فرزند بهrootCmd
اضافه کنید. -
func Execute()
: این تابع که ازmain.go
فراخوانی میشود، بایدrootCmd
را اجرا کرده و خطاهای احتمالی را مدیریت کند. -
func GetRootCmdForTest()
: این تابع در تستها استفاده میشود و شما نباید آن را ویرایش کنید!
فایل cmd/run.go
cmd/run.go
توضیح: این فایل منطق اصلی اجرای یک پروسه جدید را در خود جای داده است.
نیازمندیها:
-
struct AsyncProcessMonitor
: شما باید اینstruct
را به گونهای پیادهسازی کنید که اینترفیسmonitor.ProcessMonitor
را ارضا کند. -
func (dpm *AsyncProcessMonitor) MonitorProcess(...)
: این متد باید یک گوروتین اجرا کند. این گوروتین باید منتظر بماند تا پروسهی ورودی (proc
) تمام شود و سپس وضعیت رکورد متناظر با آنpid
را در دیتابیس بهtypes.StatusFinished
تغییر دهد. -
var runCmd = &cobra.Command{...}
: در تابعRun
این دستور، باید منطق کامل زیر را پیادهسازی کنید:- بررسی Whitelist: چک کنید که آیا فرمان ورودی در
commands.AllowedCommands
وجود دارد یا خیر. در صورت عدم وجود، اگر دستور مجاز نباشد، باید خطا را به شکل زیر چاپ کنید و هیچ رکوردی هم در دیتابیس ذخیره نشود:
- بررسی Whitelist: چک کنید که آیا فرمان ورودی در
[Dockerious] Error: Command '<command>' is not allowed.
-
آرگومانها: اگر بدون هیچ آرگومانی صدا زده شود، باید خطای پیشفرض (
requires at least 1 arg(s)
) بازگردانده شود. -
اجرای پروسه: با استفاده از
os/exec
و متدStart()
، پروسه را در پسزمینه اجرا کنید.- ثبت در دیتابیس: یک رکورد جدید برای پروسه در دیتابیس با وضعیت
types.StatusRunning
ایجاد کنید. - چاپ خروجی موفقیت: پس از اجرای موفق، پیام زیر چاپ شود:
- ثبت در دیتابیس: یک رکورد جدید برای پروسه در دیتابیس با وضعیت
[Dockerious] Started process "<command and args>" with PID: <pid>
- شروع نظارت: با استفاده از
monitor.GetProcessMonitor()
، متدMonitorProcess
را برای پروسهی جدید فراخوانی کنید تا وضعیت آن پس از اتمام، به صورت خودکار آپدیت شود.
فایل cmd/ps.go
cmd/ps.go
توضیح: این دستور برای نمایش لیست پروسههای در حال اجرا و اصلاح وضعیت رکوردهای تاریخگذشته است.
نیازمندیها:
var psCmd = &cobra.Command{...}
: در تابعRun
این دستور، باید منطق کامل زیر را پیادهسازی کنید:-
واکشی از دیتابیس: تمام پروسههایی که وضعیت آنها
types.StatusRunning
است را از دیتابیس بخوانید. -
منطق Reconciliation: برای هر پروسه، با استفاده از
os.FindProcess
و ارسال سیگنال0
، بررسی کنید که آیا واقعاً در سیستمعامل در حال اجراست یا خیر. -
آپدیت وضعیت: اگر پروسهای در سیستمعامل وجود نداشت، وضعیت آن را در دیتابیس با فراخوانی تابع
updateStatusToFinished
بهروز کنید و دیگر در خروجی نمایش داده نشود. -
چاپ خروجی: لیست نهایی پروسههایی که واقعاً در حال اجرا هستند را در قالب یک جدول مرتب چاپ کنید.
-
- برای فرمت جدول میتوانید از خط زیر کمک بگیرید:
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', tabwriter.TabIndent)
fmt.Fprintln(w, "ID\tPID\tSTATUS\tCOMMAND")
خروجی باید همیشه با هدر زیر شروع شود:
ID PID STATUS COMMAND
و در ادامه هر رکورد یک پروسه نمایش داده شود.
func updateStatusToFinished(...)
: این تابع کمکی باید یک رکورد پروسه را دریافت کرده و وضعیت آن را در دیتابیس بهtypes.StatusFinished
تغییر دهد.
نکات
-
فایلهای
db.go
وmain.go
از قبل آماده شدهاند و صرفا برای اجرا در محیط لوکال میتوانید آنها را تغییر دهید. -
تنها فایلهایی که نیاز به ویرایش دارند، فایلهای داخل پوشهی
cmd/
هستند.
چه چیزی را آپلود کنید
پس از پیادهسازی ویژگیهای خواستهشده، فقط دایرکتوریهای cmd
را فشرده کرده و به صورت یک فایل زیپ ارسال کنید.
ارسال پاسخ برای این سؤال